LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Calling a C Struct from a LV CallLibrary Function.

Actually I can positively say that the padding as you describe it should be unnecessary in the case of a structure passed by reference. The Windows ABI spec defines that any parameter passed by value that is smaller than 4 bytes will be passed in a 32 bit stack value anyhow. So that should take care of the 4 byte alignment naturally.

Rolf Kalbermatter
My Blog
0 Kudos
Message 21 of 36
(929 Views)

Thanks Nathand / Rolfk for your insight into the variable handling. Actually these finer points are mostly transperent to the normal programmer unless faced with a situation as this.

 

In fact I was hoping that the problem that I m facing is linked to either the byte alignment / endianess or both and looks like it is not.

 

In my case when I use the CLF, all functions which have a single byte argumet or a U32 that can have "any value" do not throw up an error either at LV or the DLL level. But only when I try to pass a U32 that is supposed to have a specific range of values for COB-ID , I am in trouble with the DLL return value which says it is a wrong ID is being passed. Even here the LV des not report any error.

 

Not sure if these point to any additional mistakes that we are making but still thought will share them.

Raghunathan
LabVIEW to Automate Hydraulic Test rigs.
0 Kudos
Message 22 of 36
(925 Views)
First, when I said a structure passed "by reference", I did of course mean "by value".
Then why should LabVIEW see an error if you pass an invalid value to the CLN? As far as LabVIEW is concerned is an U32 simply an U32 and if that is what the function expects all is well for LabVIEW. If instead the function would expect a pointer then it would cause an exception, which LabVIEW catches and reports as error.
Your case is different as the function expects an U32 with a certain value. LabVIEW can't know about that and consequently doesn't care, but your function returns an error. Study your functipn doc to understand what value the function expects.
Rolf Kalbermatter
My Blog
0 Kudos
Message 23 of 36
(920 Views)

Thanks Rolf for the explanation about .parameter passing.  I was making a guess about padding based on the screenshot that Kousy posted of the debugger, in which it appears that the COBID value is shifted in the structure by a few bytes, and padding seemed like one reason that could happen.  Good to know that that is only an issue when passing by reference, not by value.

0 Kudos
Message 24 of 36
(910 Views)

Indeed, I did not know that little tidbit either. I don't think I've ever had to pass a cluster by value, so I've always had to deal with the possibility of needing to put padding for byte alignment as well.

0 Kudos
Message 25 of 36
(907 Views)

I am fully in agreement with what you said, Rolfk. Of course LV has no clue on the range of values. But fortunatley I do have an idea on the range and in this case it happens to be 0x181 to 0x57F which is the PDO  COB-ID on a CanOpen network.

 

Now for some odd reason the guy who did the DLL decided  that this value will be paased via a U32 - a common problem with generic code that wants to handle every possible value under the sun.

 

Since the DLL keeps saying that I am passing a wrong value for the PDO  COB-ID, I am kind off convinced that there exists an issue in the area of variable handling between the LV code and the DLL done  in Visual C++.

 

The vendor who sold the hardware is an expert on VC++ and does not know LV.  The proprotional valve vendor just knows that his valve conforms to the CiA 406 standards and knows neither LV nor VC++. And I have no clue why the function fails.

Raghunathan
LabVIEW to Automate Hydraulic Test rigs.
0 Kudos
Message 26 of 36
(915 Views)

Tried to see the actual values posted to the ConfigSyncMan function using DebugView after calling the DLL from LV2009. The prototype of the function is :

 

short CMA_ConfigSyncMan(

unsigned char ucChannelHandle

CMA_SyncManConfig stSyncManConfig);

 

typedef struct

{

   unsigned char ucSendMode;

   unsigned char ucConsumerMode;

   unsigned long ulSyncId;

   unsigned long ulSyncCycle;

}CMA_SyncManConfig;

 

The DCF was double checked to ensure the data types as required and both methods of feeding the Struct as individual elements as well as a cluster were tried. The Cluster method was totally garbled. Atleast when using the individual elements, the first two arguments were OK.

 

If you look at the screen shot (lines 238 to 243) you will realize :

 

- The value that we give for ucChannelHandle and ucSendMode seem to reach the function OK.
- The value given for ucConsumerMode goes into the lower nibble of the ulSyncId MSB.
- The value given for ulSyncID goes into the lower nibble of ulSyncCycle MSB.
 
Does this pattern of mix up point to any obvious issue and solution thereof ??
 
Thanks.
Raghunathan
LabVIEW to Automate Hydraulic Test rigs.
0 Kudos
Message 27 of 36
(878 Views)

And how does the according Call Library Node configuration look like?

Rolf Kalbermatter
My Blog
0 Kudos
Message 28 of 36
(867 Views)

Hi rolfk,

 

Attached jpeg file shows the Call Library Node configuration of the ConfigSyncMan function call.

 

 

Thanks

 

Kousy

0 Kudos
Message 29 of 36
(857 Views)

hi guys.

I need fast help please 😞

 

i am a student in munich and i am working on my BA. I use Visual Studio 2013 so the code is in ANSI C and LV 2013 Student version.

 

I have a c strucutre like this:

 

typedef struct
{
    int32_t status;                         // Bit filed for device status
    int32_t timestamp;                // set timestamp to the current systemtime by blocked entrys
    int32_t timeout;                      // by delay or slow Device the timeout says to the system software(BS) send OUT-Report for about 1 second
                                                      // Timeout in milliseconds
    int32_t vid;                               // Vendor ID
    int32_t pid;                              // Product ID
    int32_t revision;                      // Revision (by device descriptor)
    int32_t iface;                           // Interface number
    wchar_t serialnr[WSTR_LEN];        // Serialnumber of device
}HID_INFO_PUBLIC;

 

and i make an array out of it with 16 entrys:

 

HID_INFO_PUBLIC pubtable[16];

 

 

 

Now i need to get these array with structs into a CFN with an array of clusters:

 

my function i use is kind of like this:

 

 int32_t LV_DLL_EXPORT hid_get_current_table(HID_INFO_PUBLIC *x1)
 {
     // creates memory for an address and associates the name "public" with that address
     HID_INFO_PUBLIC pubtable[16];

     hid_scan();
     hid_merge();
     hid_intern_copy_public();
     // jetzt ist public Tabelle auf dem neuesten Stand und kann in LabVIEW übertragen werden
    
     // creates a block of memory in the data space large enough to hold a structure of HID_INFO_PUBLIC with 16 entrys and sets "pointerLV" to refer to this memory block
     // (int32_t*)malloc(sizeof(HID_INFO_PUBLIC) * 16);
     x1 = pubtable;

     return 1;
 }

 

return value and parameter Value can be replaced its just an example what i need.

hid_scan searches the computer for specific devices , hid_merge makes me a comparison with another array of structs and hid_intern_copy_public copies some specific information in my pubtable (array of structs).

DLL_EXPORT is for exporting this function into LV.

 

Can somebody try to explain me how i can make this. in the attachement i put a screenshot of my LV program where i have to implement the CFN.

 

I googled the last two days how to make it but i didnt come to solution.

 

Thanks for your help.

 

 

0 Kudos
Message 30 of 36
(694 Views)