我创建了一个wpf项目,该项目具有一个包含所有我的c ++后端代码的辅助静态类。一种这样的函数定义为:
public static unsafe class Backend {
[DllImport("Mandel.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public extern static void write(void* ptr, char* path);
}
public partial class MainWindow : Window
{
public MainWindow()
{
string path = "mypath";
InitializeComponent();
unsafe
{
char *p; //convert
void* myObj = Backend.init_obj(1920, 1080);
Backend.gen(myObj);
Backend.write(myObj, p);
}
}
}
void* ptr
实际上是我的对象,为了将其编组到C#端而被强制转换。我面临的问题是,每当我尝试使用wpf中的字符串文字调用此函数时,我都会发现Visual C#无法转换此字符串,因为字符串文字是以UTF16编码的。自然,除了手动将相关字节复制到char数组外,我还尝试了其他许多事情。有提示吗?
CLR可以很好地与C / C ++代码互操作,其中之一就是在托管和非托管代码之间编排数据结构。由于字符串非常重要,因此使字符串尽可能地具有元帅化的工作很多。
作为旁注,您将void*
用于由init
创建并传递给write
的上下文对象。由于您只是将其交还,因此可以将其替换为IntPtr
,并完全避免使用unsafe
块。 IntPtr
始终是当前体系结构中指针的大小。
首先,让我们更改导入函数的声明。 CharSet.Ansi
告诉它以ANSI封送字符串。 ptr
参数变为IntPtr
[DllImport("Mandel.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public extern static IntPtr init(int width, int height);
[DllImport("Mandel.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public extern static void gen(IntPtr ptr);
[DllImport("Mandel.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public extern static void write(IntPtr ptr, string path);
从那里,您可以弄清楚如何修改该函数以取消分配ptr
和您必须调用的其他任何函数。
使用这些功能变得更加容易和整洁。您不需要unsafe
块,可以将path
直接传递给write
。
public MainWindow()
{
string path = "mypath";
InitializeComponent();
IntPtr myObj = Backend.init_obj(1920, 1080);
Backend.gen(myObj);
Backend.write(myObj, path);
}
使它起作用的原始注释:
而不是尝试自己创建
char*
参数,而是更改声明,使第二个参数为string
,然后由运行时为您编组它。因为它是ANSI字符串,所以您永远不会获得完全的Unicode保真度,但这是C ++代码创建的问题。