7

我在本机 DLL 中有一个函数,定义如下:

#include <string>
void SetPath(string path);

我试图把它放在微软的 P/Invoke Interop Assistant 中,但它在“字符串”类(我认为它来自 MFC?)上窒息。

我尝试将其封送为各种不同的类型(C# String、char[]、byte[]),但每次我得到 NotSupportedException 或 Native Assembly Exception(取决于我尝试的封送处理)。

正如任何人做过使用本机字符串类的本机/托管互操作一样?有什么办法可以对此进行元帅吗?我将不得不编写自己的 Marshaler 吗?

4

3 回答 3

6

看起来您正在尝试使用 C++ 标准库字符串类。我怀疑这将是容易的元帅。最好坚持使用 char * 和 Marshal 作为 StringBuilder。这就是我通常做的。您必须添加一个为您生成 C++ 字符串的包装器。

于 2008-10-01T17:06:41.920 回答
2

PInvoke 互操作助手仅支持 C 而不是 C++。不幸的是,MFC String 类(我相信是 CString?)是 C++,不能通过助手工作。而是尝试使用以下

void SetPath(__in const WCHAR* path);
于 2008-10-01T17:39:41.560 回答
0

是的。你可以。实际上,不仅仅是std::string, std::wstring,任何标准 C++ 类或您自己的类都可以从 C#/.NET 进行编组或实例化和调用。

从 .NET 世界中实例化 C++ 对象的基本思想是从 .NET 中分配 C++ 对象的确切大小,然后调用从 C++ DLL 导出的构造函数来初始化对象,然后您将能够调用任何访问该 C++ 对象的函数,如果任何方法涉及其他 C++ 类,您还需要将它们包装在 C# 类中,对于具有原始类型的方法,您可以简单地 P/Invoke 它们。如果你只有几个方法可以调用,那会很简单,手动编码不会花很长时间。完成 C++ 对象后,调用 C++ 对象的析构函数方法,这也是一个导出函数。如果它没有,那么你只需要从.NET 中释放你的内存。

这是一个例子。

public class SampleClass : IDisposable
{    
    [DllImport("YourDll.dll", EntryPoint="ConstructorOfYourClass", CharSet=CharSet.Ansi,          CallingConvention=CallingConvention.ThisCall)]
    public extern static void SampleClassConstructor(IntPtr thisObject);

    [DllImport("YourDll.dll", EntryPoint="DoSomething", CharSet=CharSet.Ansi,      CallingConvention=CallingConvention.ThisCall)]
    public extern static void DoSomething(IntPtr thisObject);

    [DllImport("YourDll.dll", EntryPoint="DoSomethingElse", CharSet=CharSet.Ansi,      CallingConvention=CallingConvention.ThisCall)]
    public extern static void DoSomething(IntPtr thisObject, int x);

    IntPtr ptr;

    public SampleClass(int sizeOfYourCppClass)
    {
        this.ptr = Marshal.AllocHGlobal(sizeOfYourCppClass);
        SampleClassConstructor(this.ptr);  
    }

    public void DoSomething()
    {
        DoSomething(this.ptr);
    }

    public void DoSomethingElse(int x)
    {
        DoSomethingElse(this.ptr, x);
    }

    public void Dispose()
    {
        Marshal.FreeHGlobal(this.ptr);
    }
}

有关详细信息,请参阅以下链接,

C#/.NET PInvoke 互操作 SDK

(我是SDK工具的作者)

一旦为 C++ 类准备好 C# 包装类,它就很容易实现ICustomMarshaler,以便您可以从 .NET 编组 C++ 对象。

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.icustommarshaler.aspx

于 2013-04-15T03:31:15.320 回答