What You’ll Learn 🧰
Understand what the DSRemote DLL is and why it simplifies controlling and retrieving data from DewesoftX compared to DCOM or Dewesoft NET protocols
Install the DSRemote library (version ≥ 1.1.0), including examples in C++, Python, and LabVIEW
Establish connections to DewesoftX via DCOM or Dewesoft NET, and understand when each is appropriate
Load and manage DewesoftX setups programmatically, including showing or hiding the UI
Start and stop acquisitions remotely, and read live data streams over TCP/IP or DCOM
Write values to control channels to manipulate measurement parameters in real time
Retrieve metadata from channels—such as names, units, and scaling—for seamless integration into external applications
Use DSRemote library functions to feed data into databases or post-processing tools, enhancing automation workflows
Course overview
The DSRemote Library course introduces a streamlined way to interact with DewesoftX from external applications via a simple C‑style DLL. It helps demystify complex remote communication methods—DCOM and Dewesoft NET—by providing a clean interface that supports both protocols.
You’ll begin with installation steps: downloading the DSRemote ZIP package, using version 1.1.0 or newer for NET compatibility, and exploring example code in Python, C++, and LabVIEW . The course covers creating a DSRemote instance via dsconCreateInstance(), establishing connections with DewesoftX (empty string for DCOM or IP:port:port syntax for NET), and using functions to load setups, show/hide UI, and start/stop measurements.
You’ll also gain hands-on experience retrieving real-time data—reading from multiple channels—and sending control commands via DSRemote’s API. The library supports extracting channel units or names for external processing, and offers a flexible communication layer ideal for integrating DewesoftX into automation and data-logging systems.
By the end of the course, you’ll be able to embed DewesoftX within your own software workflows, using C, C++, Python, LabVIEW, or any environment capable of calling C‑style DLLs. This opens up powerful possibilities, from remote control and data collection to real-time database storage and post‑processing analysis.
Introduction to DSRemote library
Have you ever wanted to control DewesoftX, only to find that DCOM (Distributed Component Object Model) is difficult to understand and the Dewesoft NET protocol even more complex? With the help of a C DLL (Dynamic Link Library) called DSRemote, you can now control DewesoftX and retrieve data more easily than ever before.
How to install the DSRemote library
To install DSRemote, visit our website and navigate to the Development section. There, you will find the DSRemote download. Please note that you must be logged in to access the Developer section.
After downloading, you will receive a ZIP file containing examples written in Python, C++, and LabVIEW. Version 1.1.0 or newer is required to use the Dewesoft NET option.
Overview of DSRemote
1int dsconCreateInstance(DSXInstanceHandle* handle, int connectionType);
The first parameter is a handle passed by reference. This handle represents the connection to the DewesoftX software.
The second parameter defines the type of connection to be established with DewesoftX.
As mentioned earlier, two connection types are supported: DCOM and Dewesoft NET.
In the DLL, they are defined as:
1typedef enum {
2 DSX_CONNECTION_TYPE_DCOM = 0,
3 DSX_CONNECTION_TYPE_NET = 1
4} DSX_CONNECTION_TYPE;
10
Represents a DCOM connection.
11
Represents a NET connection. To establish a NET connection, call the function as follows:
10
Represents a DCOM connection.
11
represents a NET connection.
To establish a NET connection, call the function as follows:
1dsconCreateInstance(dsconInstance, DSX_CONNECTION_TYPE_NET)
After calling this function, an instance is created that will be used to control DewesoftX. With this instance, other functions can then be called. However, before DewesoftX can be fully controlled, a connection must first be established. To do this, call the following function:
1int dsconConnect(DSXInstanceHandle handle, char* connectionString)
The first parameter is the instance obtained from the dsconCreateInstance function, and the second parameter is a string that provides the connection information. If the DCOM protocol is used, this parameter can be left empty. However, for the Dewesoft NET protocol, the parameter must include connection details separated by colons. This string specifies the address to connect to over Ethernet.
For example, to connect to a computer with the IP address 10.2.10.254, using port 8999 for Telnet communication and port 8001 for data transmission, the string would be defined as follows:
1“10.2.10.254:8999:8001”
You can read more about these settings in the Dewesoft NET Pro Tutorial or in the user manual.
Once connected to DewesoftX, you are ready to begin performing actions.
Example - reading and writing data over NET
Now let's take a look at an example
1from ctypes import *
2import ctypes from ctypes.wintypes import *
3import time
4import numpy as np
5
6def doErrCheck(err_code, descr):
7 if err_code < 0:
8 print(str(descr) + " errCode: " + str(err_code))
9 return err_code
10
11hllDll = WinDLL ("C:\\DXEProjects\\Tools\\DSRemoteConnect\\DSRemoteConnect\\Debug\\DSRemoteConnect64.dll")
12dsconInstance = HANDLE()
13doErrCheck(hllDll.dsconCreateInstance(pointer(dsconInstance), 1), "dsconCreateInstance")
14charArray = create_string_buffer("10.2.120.255:8999:8001".encode())
15doErrCheck(hllDll.dsconConnect(dsconInstance, charArray), "dsconConnect")
16numChannels = c_size_t()
17doErrCheck(hllDll.dsconGetChannelCount(dsconInstance, byref(numChannels)), "dsconGetChannelCount")
18print(numChannels.value)
19
20# Second way of enumerating Channels
21labelsPtr = pointer((POINTER(ctypes.c_char_p) * numChannels.value)()) localValue = c_size_t(numChannels.value)
22hllDll.dsconEnumerateChannels(dsconInstance, labelsPtr, byref(localValue))
23name = (c_char * 50)()
24ch_name = ctypes.cast(name, c_char_p)
25unit = (c_char * 50)()
26ch_unit = ctypes.cast(name, c_char_p)
27ch_instances = []
28
29for i in range(0, numChannels.value):
30 name = (c_char * len(labelsPtr[0][0][i]))()
31 ch_index = ctypes.cast(name, c_char_p)
32 ch_index.value = labelsPtr[0][0][i]
33 ch_instance = HANDLE()
34 hllDll.dsconCreateChannelInstance(dsconInstance, ch_index, pointer(ch_instance))
35 ch_instances.append(ch_instance)
36 hllDll.dsconChannelGetName(ch_instances[i], ch_name, 50)
37 print(ch_name.value)
38 hllDll.dsconGetChUnit(ch_instances[i], ch_unit, 50)
39 print(ch_unit.value)
40
41doErrCheck(hllDll.dsconChannelSetTransferred(ch_instances[len(ch_instances) - 1], False), 'dsconChannelSetTransferred')
42doErrCheck(hllDll.dsconStartMeasurement(dsconInstance), "dsconStartMeasurement")
43data2 = ctypes.cast((c_double * 100000)(), POINTER(c_double))
44time_stamps2 = ctypes.cast((c_double * 100000)(), POINTER(c_double))
45count = 0
46while True:
47 try:
48 countData2 = c_size_t(100000)
49 for i in range(len(ch_instances)):
50 doErrCheck(hllDll.dsconChannelReadScalarData_2(ch_instances[i], data2, time_stamps2, byref(countData2)), "dsconChannelReadScalarData_2"
51
52 doErrCheck(hllDll.dsconControlChannelWriteData(ch_instances[1], c_double(0.69 + count)), "dsconControlChannelWriteValue1")
53 doErrCheck(hllDll.dsconControlChannelWriteData(ch_instances[2], c_double(0.70 + count)), "dsconControlChannelWriteValue2")
54 doErrCheck(hllDll.dsconControlChannelWriteData(ch_instances[3], c_double(0.71 + count)), "dsconControlChannelWriteValue3")
55 count += 1
56 except:
57 print("While interrupted")
58 break
59
60print("Finally")
61doErrCheck(hllDll.dsconStopMeasurement(dsconInstance), "dsconStopMeasurement")
62doErrCheck(hllDll.dsconDisconnect(dsconInstance), "") # this will close Dewesoft.exe and clear the DCOM
63for i in range(0, numChannels.value - 1):
64 doErrCheck(hllDll.dsconFreeChannelInstance(ch_instances[i]), "dsconFreeChannelInstance") # this will free chnl instances of dll
65doErrCheck(hllDll.dsconDestroyInstance(dsconInstance), "dsconDestroyInstance") # this will free dll instance
The example is written in Python and uses the Dewesoft NET protocol. It first outputs the channels defined in the setup, displaying their names and units. After listing this information, the script switches to measurement mode and begins reading data. Once the data is acquired, it writes values to a control channel.
Now, let’s examine the code section by section.
In the following part, the available channels are listed, and each channel’s name and unit are printed.
1numChannels = c_size_t()
2doErrCheck(hllDll.dsconGetChannelCount(dsconInstance, byref(numChannels)), "dsconGetChannelCount")
3print(numChannels.value)
4
5# Second way of enumerating Channel
6labelsPtr = pointer((POINTER(ctypes.c_char_p) * numChannels.value)())
7localValue = c_size_t(numChannels.value)
8hllDll.dsconEnumerateChannels(dsconInstance, labelsPtr, byref(localValue))
9name = (c_char * 50)()
10ch_name = ctypes.cast(name, c_char_p)
11unit = (c_char * 50)()
12ch_unit = ctypes.cast(name, c_char_p)
13ch_instances = []
14
15for i in range(0, numChannels.value):
16 name = (c_char * len(labelsPtr[0][0][i]))()
17 ch_index = ctypes.cast(name, c_char_p)
18 ch_index.value = labelsPtr[0][0][i]
19 ch_instance = HANDLE()
20 hllDll.dsconCreateChannelInstance(dsconInstance, ch_index, pointer(ch_instance))
21 ch_instances.append(ch_instance)
22 hllDll.dsconChannelGetName(ch_instances[i], ch_name, 50)
23 print(ch_name.value)
24 hllDll.dsconGetChUnit(ch_instances[i], ch_unit, 50)
25 print(ch_unit.value)
26 print(ch_unit.value)
Before looping through all the channels, we first need to determine how many channels are available. To retrieve this information, call the following function:
1int dsconGetChannelCount(DSXInstanceHandle handle, size_t* count);
The first parameter is the instance described in the previous section. The second parameter is a value passed by reference. After calling this function, the number of channels in DewesoftX will be stored in this variable.
Before accessing the properties, we need to obtain the unique ID that represents each channel. To retrieve the unique IDs, the appropriate function must be called.
1int dsconEnumerateChannels(DSXInstanceHandle handle, ChannelIdList* channelIdList, size_t* count);
This function returns values by reference. The second parameter provides an array of strings, where each element represents a unique ID for a DewesoftX channel. The last parameter specifies the number of channels in the array. These unique IDs are then used to create DewesoftX channel instances. To create a channel instance, the appropriate function must be called.
1int dsconCreateChannelInstance(DSXInstanceHandle handle, ChannelID id, ChannelInstanceHandle* chInstance);
The channel instance is returned as the third parameter by reference. Once obtained, the channel instance can be used to retrieve information such as the channel name and unit. To access the channel name, the appropriate function must be called.
1int dsconChannelGetName(ChannelInstanceHandle channel, char* name, size_t len);
To retrieve the channel unit, the appropriate function must be called.
1int dsconGetChUnit(ChannelInstanceHandle handle, char* resultUnit, size_t len);
After each function call, the result is printed to the standard output.
In the next section, we will examine how to read from and write data to channels. Let’s take a closer look.
1doErrCheck(hllDll.dsconStartMeasurement(dsconInstance), "dsconStartMeasurement")
2data2 = ctypes.cast((c_double * 100000)(), POINTER(c_double))
3time_stamps2 = ctypes.cast((c_double * 100000)(), POINTER(c_double))
4count = 0
5
6while True:
7 try:
8 countData2 = c_size_t(100000)
9 for i in range(len(ch_instances))):
10 doErrCheck(hllDll.dsconChannelReadScalarData_2(ch_instances[i], data2, time_stamps2, byref(countData2)), "dsconChannelReadScalarData_2")
11
12 doErrCheck(hllDll.dsconControlChannelWriteData(ch_instances[1], c_double(0.69 + count)), "dsconControlChannelWriteValue1")
13 doErrCheck(hllDll.dsconControlChannelWriteData(ch_instances[2], c_double(0.70 + count)), "dsconControlChannelWriteValue2")
14 doErrCheck(hllDll.dsconControlChannelWriteData(ch_instances[3], c_double(0.71 + count)), "dsconControlChannelWriteValue3")
15 count += 1
16
17 except:
18 print("While interrupted")
19 break
20
21print("Finally")
22doErrCheck(hllDll.dsconStopMeasurement(dsconInstance), "dsconStopMeasurement")
23doErrCheck(hllDll.dsconDisconnect(dsconInstance), "") # this will close Dewesoft.exe and clear the DC
24for i in range(0, numChannels.value - 1)
25 doErrCheck(hllDll.dsconFreeChannelInstance(ch_instances[i]), "dsconFreeChannelInstance") # this will free chnl instances of dewesoft
26doErrCheck(hllDll.dsconDestroyInstance(dsconInstance), "dsconDestroyInstance") # this will free dll instance
Before reading or writing data, we must first switch to Measure mode. To do this, call the appropriate function.
1int dsconStartMeasurement(DSXInstanceHandle handle);
After this call, data can be read from and written to channels. The library supports reading data from any channel, but writing is supported only for control channels. To determine whether a channel is a control channel, the appropriate function must be called.
1int dsconIsChannelControl(ChannelInstanceHandle handle, bool* result);
Before reading the data, a local buffer must be allocated. The channel samples will then be stored in this buffer. In the Python example, the following code illustrates this process:
1data2 = ctypes.cast((c_double * 100000)(), POINTER(c_double))
2time_stamps2 = ctypes.cast((c_double * 100000)(), POINTER(c_double)
We preallocate a local buffer for data and timestamps. The buffer size is set to 100,000 double values. The required buffer size depends on how many values will be copied from DewesoftX. If the preallocated buffer is too small, samples in DewesoftX will be lost because they will be overwritten. The following function illustrates this:
1int dsconChannelReadScalarData_2(ChannelInstanceHandle handle, double* data, double* timestamps, size_t * count);
The function accepts several parameters. The first parameter is a channel instance, which represents the channel from which data will be read. The second and third parameters specify the preallocated buffers, while the fourth parameter defines the buffer size. If the number of available samples is smaller than the buffer size, the function automatically adjusts to the number of samples provided.
As mentioned earlier, there is also a function for writing values to control channels. This function is structured as follows:
1int dsconControlChannelWriteData(ChannelInstanceHandle handle, double data);
Similar to dsconChannelReadScalarData, the first parameter represents the channel instance connected to the DewesoftX channel. The second parameter specifies the value to be written to the control channel.
Once the measurement is complete, the following function must be called:
1int dsconStopMeasurement(DSXInstanceHandle handle);
After completing the measurement, and before stopping the program, it is necessary to disconnect from DewesoftX. To do this, call the following function:
1int dsconDisconnect(DSXInstanceHandle handle);
After disconnecting, it is also important to ensure that the software closes properly. This occurs when all instances created during the execution of the application are freed. To achieve this, use the following functions:
1int dsconFreeEnumerateChannels(DSXInstanceHandle handle, ChannelIdList* channelIdList)
2int dsconFreeChannelInstance(ChannelInstanceHandle chInstance)
3int dsconDestroyInstance(DSXInstanceHandle handle);
The dsconFreeEnumerateChannels function is used to free the array of strings created during the call to dsconEnumerateChannels. The dsconFreeChannelInstance function is used to release the channel instances that were created using the dsconCreateChannelInstance function. Once all other instances have been freed, the final step is to call dsconDestroyInstance to completely release the main instance.
Page 1 of 5