[英]How to PInvoke C++ DLL Function from C#
我正在尝试从C#应用程序中访问显微镜。 该SDK是用C ++编写的,我无法将Dll添加为我的应用程序中的引用(由于它们是非托管代码)。 结果,我发现我将需要使用DllImport才能将功能与C#一起使用。
不幸的是,这似乎让我感到头疼。
例如,一些C ++代码(来自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);
这是稍后使用的方式:
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);
如何将其转换为C#代码? 我已经尝试过类似的东西:
[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")]
但是基本上我不知道自己在做什么以及下一步需要做什么(例如如何定义函数,如何处理C ++代码中的“接口”,结构是否正确转换等等)。 。
C#中的结构定义要比您的复杂。 看看PInvoke Interop Assistant。 https://clrinterop.codeplex.com/releases/view/14120它对初始属性很有帮助。
首先,要将这些wchar_t
数组转换为.NET string
您将需要设置其他属性 。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct CameraInfo
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
string camera_name; // camera head type
...
接下来,方法CamDiscoverCameras
返回一个指向struct的指针 ,因此在.NET中,您实际上将收到一个IntPtr
,然后使用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;
}
而且不要忘了清理-从您的代码看来,该结构已在C ++代码中分配了,因此您可能必须将IntPtr传递回C ++代码才能对其进行取消分配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.