LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

String Memory Management using Call Library Function

Solved!
Go to solution

Hi,

I've been going through the discussion boards extensively on this issue trying to find a clear cut solution but I think my case may be a bit too specific for that route.

 

Anyway, I am working on interfacing with a motion controller (HIMC from HIWIN) using a DLL provided and the call library function tool from LabVIEW. I have already used the Import Shared Library wizard to obtain VIs for the simpler functions but I am stuck specifically on the HIMC_ConnectCtrl function. It has one input which is a relatively complex structure with nested structures inside.

 

Here is how the function is called:

int HIMC_ConnectCtrl( const ComInfo com_info, int *p_ctrl_id );

 

And here is how ComInfo is structured: 

typedef struct {

ComType type;

struct { char ip[20]; char port[12]; } TCP_IP;
struct { char com_port_name[80]; int baud_rate; } RS232;
struct { char autoExecExe; } Simulator;

} ComInfo;

 

The ComType enum is structured as such:

typedef enum {

COM_TYPE_TCPIP,

COM_TYPE_RS232,

COM_TYPE_SIMULATOR

} ComType;

 

The function returns a 0 if successful and anything else if it fails, every time I run the VI it returns this value:  16777226. I believe the issue is either coming from the structure of the char arrays or the enum. I've supplied the VI I modified for this special structure but I'm really at a dead end here and I don't know what to try next. Any suggestions?

 

(If there is a similar post I may have missed, please direct me there.)

Download All
0 Kudos
Message 1 of 26
(3,089 Views)

Similar posts in the sense of the underlaying problem are on this forum several hundreds at least. The difficulty is that without a solid understanding of how a C compiler works when aligning data structures in memory each of those posts will look completely different to you.

 

First you need to understand that each of these elements is fully inlined in the structure as they are fixed size elements at compile time. The developer was most likely himself not a real C programmer or the DLL was not implemented in C either, since the settings for TCP/IP and RS-232 are mutually exclusive so use of the union C feature would have been useful.

 

You basically want to create a cluster with an uint32 for the ComType enum, then a cluster inside with 20 uint8 for ip, another cluster of 12 uint8 for port, then a cluster with 80 uint8 for com_port_name, then an int32 for baudrate and last but not least an int8 for autoExecExe.

Rolf Kalbermatter
My Blog
Message 2 of 26
(3,059 Views)

Thank you for the concise explanation, Rolf.

 

I was unsure whether bundling the info for TCP/IP or RS232 really did anything when compiled so I nested the clusters for each anyway. I believe the DLL was implemented in a propriety language HIWIN developed called "HMPL" but I'm not entirely sure. They have an example program in c# and c++ that connects to the controller which I have been using as sort of a guide.

 

I tried the changes you suggested however I was unsuccessful. I included the files I'm using but I'm fairly certain I didn't make a mistake. 

 

I also included a picture of a section of the header file in question if that offers more insight into what the issue may be.

0 Kudos
Message 3 of 26
(3,041 Views)

It doesn't seem like you followed rolfk's advice.

 

You need to have a clusters within clusters. For example, your Comtype TCP_IP is a cluster, but you are just showing a flat structure, Cluster[ Cluster[TCP_IP], ... ]

 

mcduff

0 Kudos
Message 4 of 26
(3,033 Views)

In the VI you've implemented this:

 


@JustinB_Everix wrote:

typedef struct {

ComType type;

struct { char ip[20]; char port[12]; } TCP_IP;
struct { char com_port_name[80]; int baud_rate; } RS232; 

} ComInfo;


struct { char autoExecExe; } Simulator;  seems to be missing?

0 Kudos
Message 5 of 26
(3,020 Views)

In my original post, I structured the .ctl as nested clusters however I don't believe it makes a difference either way. When I ran the VI in both configurations I still didn't receive the correct return value of 0. I am able to connect to the motion controller through the sample code they provided in C# using the same TCP/IP information I tried with the call library function.

0 Kudos
Message 6 of 26
(3,007 Views)

It's right there at the bottom of the typedef in my original post.

0 Kudos
Message 7 of 26
(3,002 Views)

AFAIK, The data should be flattened in memory, so you might as well send a string or [u8] with the data.

 

But in the previous VI, the last element was missing. That will make things crash.

 

You could maybe output the data C# is sending? Then spot the differences? Or even replace the real dll with a dummy dll, and analyze the data C# is sending there? It could even be a LV dll...

0 Kudos
Message 8 of 26
(3,000 Views)

That's a good idea, I'm going to monitor the differences when I call the same function from Visual Studio and LV. I'm sure that should show me something.

0 Kudos
Message 9 of 26
(2,990 Views)

Would it be possible to backsave the VIs for LabVIEW 2016 or earlier. I'm still in the aftermath of a project that started in LabVIEW 2016 and includes FPGA, RT and several industrial protocols and really hesitate to damage that working installation by adding a new LabVIEW installation to my system.

 

As to cluster, within cluster within cluster the OP is right, this should not have any influence for the data alignment in memory for at least this specific structure.

Rolf Kalbermatter
My Blog
0 Kudos
Message 10 of 26
(2,986 Views)