I am trying to access a Microscope from within my C# application. The SDK is written in C++ and I can not add the Dlls as references in my application (due to them being unmanaged code). As a result I found out that I will need to use DllImport in order to use the functions with C#.
Unfortunately this seems to be way over my head.
As an example some of the C++ code (from a sample app 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 this is how it is used later on:
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 have 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 basically I have no idea of what I am doing and what needs to be done next (like how the function needs to be defined, how to deal with that "interface" in the C++ code, is the structure converted correctly and so on).
First of all, to convert those wchar_t
arrays to .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 method CamDiscoverCameras
returns a pointer to the struct, so in .NET you will be actually receiving an IntPtr
and then converting that pointer to a struct using Marshal.PtrToStructure
method:
[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 cleanup - from your code it seems that the structure is being allocated somewhere in C++ code, so you likely would have to pass the IntPtr back to C++ code for it to deallocate it.
Your struct definition in C# is a bit more complex then yours. Have a look at the PInvoke Interop Assistant. https://clrinterop.codeplex.com/releases/view/14120 It helps a lot with the initial attributes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With