如何通过p/invoke传递字符串

本文关键字:字符串 invoke 何通过 | 更新日期: 2023-09-27 18:26:31

我需要通过p/invoke传递一个字符串,它只是一个文件名,类似于"desc.xml"。我不在乎它是std::string还是char*,或者可能是其他类型的(我可以转换为appropiate类型)。我应该如何申报签名?

在c#方面,我期待类似的东西:

    [DllImport("Native.dll"), SuppressUnmanagedCodeSecurity]
    public static extern void Initialize(/*TODO: how to pass string?*/);

在c++方面,我期待类似的东西:

__declspec(dllexport) void Initialize(char* fileName);

或CCD_ 3而不是CCD_ 4

__declspec(dllexport) void Initialize(std::string& fileName);

我希望它能这样使用:

Initialize("desc.xml");

问题是我应该如何准确地声明参数。

如何通过p/invoke传递字符串

public static extern void Initialize(string filename);

还要向DllImport("Native.dll")中添加一个CharSet,以匹配C++端的内容(CharSet.Ansi表示char*CharSet.Unicode表示wchar*)。

假设您想要接收ANSI编码的文本,您应该像这样声明C++代码:

__declspec(dllexport) void Initialize(const char* fileName);

这将使用默认的__cdecl调用约定。该文本将作为指向以null结尾的char数组的指针传递。

在C#方面,你这样声明:

[DllImport("Native.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern void Initialize(string fileName);

没有必要指定字符集,因为默认值是`ANSI。如果你想明确(在我看来这不是一个坏主意),那么你可以这样写:

[DllImport("Native.dll", CallingConvention=CallingConvention.Cdecl, 
    CharSet=CharSet.Ansi)]
public static extern void Initialize(string fileName);

如果按原样编译C++代码,函数的名称将被破坏。您必须使用DllImport属性的EntryPoint参数来指定损坏的名称。作为替代方案,您可以将本机代码对函数的声明封装在extern "C"块中,以抑制损坏。