LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

PICAM SDK, Call Library Function, crashes LV

Solved!
Go to solution

Hello,

I have very tiny (zero) experience with external DLL calls. I try to use a SDK called PICAM to interface a Princeton Instr. camera (driver installed successfully under Win7, x64) from LabVIEW.

I attach the SDK manual, and also the public header file.

I started to develop step by step and test some basic VIs. So far the library init/uninit, and the Camera_open/close functions seem to work (no error response).

 

However, the next step would be to call the "int32_t Picam_GetCameraID(uint32_t camera, void *id);" function. I got this function prototype from an unfinished LV project I inherited from an ex-colleague. I have the strong feeling, that the function prototype / data types are not OK, so thus I get LV crash when I call this particular function. I try to figure out from the manual, how to properly pass/get data types to/from LV. No success so far 😞

Someone could give me some hints please?

(the DLL import wizard did not work, complaint about many type mismatches).

I also attach some more files (the lvlib i have so far, the header file, and the manual), they might help you to help me faster. If you need any more info, just write me please!

Thanks very much, I am really stuck with this project now! 🙂

 

Download All
0 Kudos
Message 1 of 89
(6,626 Views)

So practically my question is that, if we have the following struct in C code, we need to create such typdef cluster as shown in the screenshot below? Or this is not the correct way?

 

typedef struct PicamCameraID
{
    PicamModel             model;
    PicamComputerInterface computer_interface;
    pichar                 sensor_name[PicamStringSize_SensorName];
    pichar                 serial_number[PicamStringSize_SerialNumber];
} PicamCameraID;

Types what I have found in the header file (as much as I can see in the header file, pichar is not clear where is declared/defined...):

PicamModel: enum

PicamComputerInterface: enum

 

picamID_ss2.png

 

Edit: I have found some starting hint which looks similar to my case:

https://forums.ni.com/t5/LabVIEW/dll-struct-to-LabVIEW-cluster/m-p/2235830/highlight/true#M711119

I try to experiment tomorrow...

0 Kudos
Message 2 of 89
(6,598 Views)
Solution
Accepted by Blokk

Replace the array elements (sensor_name and serial_number) with clusters containing the correct number of elements. The sizes are defined in the header file:

    PicamStringSize_SensorName     =  64,
    PicamStringSize_SerialNumber   =  64,
    PicamStringSize_FirmwareName   =  64,
    PicamStringSize_FirmwareDetail = 256

So replace the sensor_name and serial_number arrays with clusters containing 64 U8 elements each. Also, make sure that your enums have the correct representation. Most likely they should be U32, but it's possible that the compiler decided to use something smaller.

Message 3 of 89
(6,589 Views)

Thanks very much for the guide! I can test it tomorrow morning, and give feedback here! 🙂

0 Kudos
Message 4 of 89
(6,587 Views)
Solution
Accepted by Blokk

The two enums in the beginning throw a bit of a wrench into the engine. Traditionally in C an enum is only as large as is needed to contain the largest numeric valid defined for it. So it can be as small as one byte. However putting them into a struct suddenly also adds alignment concerns into the recipe.

From a brief look at the header file for this it would seem that the enums itself should probably be an uint16 for the PicamModel as it contains values bigger than 127 but not bigger than 32767 and the PicamInterface is probably an uint8. But you will have to see if that really aligns up and you get the correct string data in the sensor_name and serial_number elements.

The fixed size char arrays you cannot represent as LabVIEW string or array handles. That is completely different. Instead you should add embedded clusters of 64 U8 values into the main cluster, just as Nathan has recommended.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 5 of 89
(6,561 Views)

Guys, your support is just simply great! 🙂

It works! Smiley Very Happy

See snippet below. By the way, I get lots of trailing \00 terminators at the end of strings, I guess due to the byte-array to string function? What is the neat way to remove these?

Another thing, is I do not get anything for the ComputerInterface enum, even I tried U8, U16 and U32 data types for the Menu Ring...

Thanks again, I will be back if I get stuck with another struct! 😄

 

PICAM.lvlib_TESTER.png

0 Kudos
Message 6 of 89
(6,557 Views)

It seems you should make those two enums both an uint32 to align the strings better.

Removing the superfluous NULL bytes at the end is done be replacling the Byte Array to String functions with your own Zero Terminated Byte Array to String subVI like the attached one. 

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 7 of 89
(6,550 Views)

Thanks! Now it works 100% fine, no termination character flood, and I also get the proper ComputerInterface value (USB2.0 I use):

 

PICAM.lvlib_TESTER_uj.png

0 Kudos
Message 8 of 89
(6,543 Views)

Ok, now this seems even more tricky, what about types of "const PicamCameraID** "? 🙂 I tried some settings, but no success so far (error I get: "PicamError_UnexpectedNullPointer") 🙂 Thanks a lot for guidance! 🙂

Manual page 29.:

The syntax for Picam_GetAvailableCameraIDs() is:
PICAM_API Picam_GetAvailableCameraIDs(
const PicamCameraID** id_array,
piint* id_count);

Call from LabVIEW:

PICAM.lvlib_Get_Available_camera_IDs_BD.png

getavailablecmaeraids.png

0 Kudos
Message 9 of 89
(6,531 Views)

There is no way to configure a Call Library Node parameter to be directly a reference pointer. Somewhere NI had to draw a line and they did it at this point, since in C you can in fact create arbitrary complex levels of references of references of pointers.

 

The way to go for this without creating a wrapper DLL is to configure this parameter as a pointer sized integer passed by reference and then using LabVIEW::MoveBlock() or similar calls to copy out the information from that pointer. And obviously call Picam_DestroyCameraIDs() afterwards for this pointer or you create memory leaks.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 10 of 89
(6,524 Views)