c++ /CLI双指针类型转换为ref IntPtr,用于c#访问

本文关键字:IntPtr 用于 访问 ref CLI 指针 类型转换 c++ | 更新日期: 2023-09-27 18:03:27

我正在用c++/CLI编写一个围绕C DLL的包装器,以便可以通过托管程序集在c#中访问它。使用直接P/Invoke通过c#访问C函数是不可能的,因为C DLL会引发异常,而这些异常无法使用P/Invoke正确捕获(在跨C/c#边界移动时异常消息丢失)。因此,我们的想法是创建一个托管的CLI DLL,它内部调用C DLL并将异常包装到CLI的exception类。

C DLL函数有这样的声明

void InitDB(void **handle);

c#应用程序需要以下声明

void InitDB_cs(ref IntPtr handle);

为了实现这一点,我创建了c++/CLI函数,声明如下

void InitDB_clr(IntPtr %handle);

然而,我无法将ref InPtr类型转换为C函数。我试着使用下面的代码,但似乎不能得到正确的类型转换。

void InitDB_clr(IntPtr %handle)
{
pin_ptr<IntPtr> ptr = handle.ToPointer();
InitDB(&ptr);
}

以上代码的错误信息

error C2440: 'initializing' : cannot convert from 'void *' to 'cli::pin_ptr<Type>'
1>        with
1>        [
1>            Type=System::IntPtr
1>        ]
1>        Conversion from 'void*' to pointer to non-'void' requires an explicit cast
1>error C2664: 'InitDB' : cannot convert parameter 1 from 'cli::pin_ptr<Type> *' to 'void **'
1>        with
1>        [
1>            Type=System::IntPtr
1>        ]
1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

c++ /CLI双指针类型转换为ref IntPtr,用于c#访问

这是一个out参数,而不是真正的ref,对吗?

void InitDB_clr(IntPtr% handle)
{
    void* ptr /* = handle.ToPointer() */;
    InitDB(&ptr);
    handle = IntPtr(ptr);
}

您可以在不安全的上下文中使用c#并使用

unsafe void InitDB_cs(IntPtr** handle);