How to execute PInvoke C ++ DLL function with C #

I am trying to access the microscope from my C # application. The SDK is written in C ++, and I cannot add Dlls as links in my application (due to their unmanaged code). As a result, I found out that I would need to use DllImport to use C # functions.

Unfortunately, this looks like my head.

An example is C ++ code (from an example application included in the SDK):

interface Camera; typedef Camera * CameraHandle; struct CameraInfo { wchar_t camera_name[64]; // camera head type wchar_t controller_name[64]; // controller type wchar_t firmware_version[64]; // firmware version long lib_id; // library ID long controller_id; // controller ID long camera_id; // camera ID CameraHandle handle; // handle to opened camera long status; // status (0 = available) CameraInfo() { memset(this,0,sizeof(*this)); } }; typedef struct CameraInfo CameraInfo; CamDiscoverCameras(OUT const struct CameraInfo ** info, OUT long * count); 

And here is how it is used later:

 CamResult result; //enum CamResult{...} const CameraInfo* camera_info = NULL; long camera_count = 0, pre_lib_id, pre_controller_id; result = CamDiscoverCameras(&camera_info, &camera_count); 

How do I convert this to C # code? I already tried something like:

  [StructLayout(LayoutKind.Sequential)] struct CameraInfo { string camera_name; // camera head type string controller_name; // controller type string firmware_version; // firmware version int lib_id; // library ID int controller_id; // controller ID int camera_id; // camera ID public IntPtr handle; // handle to opened camera int status; // status (0 = available) } [DllImport("Cam.dll", EntryPoint = "CamDiscoverCameras")] 

But in principle, I have no idea what I'm doing and what needs to be done next (for example, how a function should be defined, how to deal with this “interface” in C ++ code, whether the structure is correctly transformed, and so on).

+5
source share
2 answers

First of all, to convert these wchar_t arrays to a .NET string , you will need to set additional attributes .

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct CameraInfo { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] string camera_name; // camera head type ... 

Next, the CamDiscoverCameras method returns a pointer to a structure, so in .NET you actually get IntPtr , and then convert that pointer to a structure using Marshal.PtrToStructure :

 [DllImport("Cam.dll", EntryPoint = "CamDiscoverCameras")] // you can create enum of ints here and return it static extern int CamDiscoverCameras(out IntPtr info, out int count); CameraInfo DiscoverCameraInfos() { IntPtr info; int count; int camResult = CamDiscoverCameras(out info, out count); var camInfo = (CameraInfo) Marshal.PtrToStructure(info, typeof(CameraInfo)); // cleanup code - pass your IntPtr to C++ code // for it to delete the struct as it seems it was allocated there return camInfo; } 

And don't forget to clear it - it seems from your code that the structure stands out somewhere in the C ++ code, so you will most likely have to pass IntPtr back to C ++ code to free it.

+2
source

Your definition of structure in C # is a little more complicated than yours. Look at the PInvoke assistant assistant. https://clrinterop.codeplex.com/releases/view/14120 This helps a lot with the initial attributes.

+2
source

Source: https://habr.com/ru/post/1204317/


All Articles