0

我有一个 C++ DLL,其中导出了以下函数。

double getDouble(std::wstring filename, std::string ID, status &stCode);

int getInt(std::wstring filename, std::string ID, status &stCode);

float getFloat(std::wstring filename, std::string ID, status &stCode);

string getString(std::wstring filename, std::string ID, status &stCode);

int* getIntArray(std::wstring filename, std::string ID, status &stCode);

float* getFloatArray(std::wstring filename, std::string ID, status &stCode);

string* getStringArray(std::wstring filename, std::string ID, status &stCode);

其中状态是枚举类型...

现在我想在我的 C#.NET 应用程序中使用这个 DLL……谁能告诉我如何在 C# 中声明受人尊敬的方法,并且可以调用这些方法……提前致谢……

4

2 回答 2

0

Yes. You can. Actually, not std::string, std::wstring, any standard C++ class or your own classes can be marshaled or instantiated and called from C#/.NET. You will need to write a wrapper class for each of the C++ class before you can marshal them in .NET.

The basic idea of instantiating a C++ object from .NET world is to allocate exact size of the C++ object from .NET, then call the constructor which is exported from the C++ DLL to initialize the object, then you will be able to call any of the functions to access that C++ object, if any of the method involves other C++ classes, you will need to wrap them in a C# class as well, for methods with primitive types, you can simply P/Invoke them. If you have only a few methods to call, it would be simple, manual coding won't take long. When you are done with the C++ object, you call the destructor method of the C++ object, which is a export function as well. if it does not have one, then you just need to free your memory from .NET.

Here is an example.

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);
    }
}

For the detail, please see the below link,

C#/.NET PInvoke Interop SDK

(I am the author of the SDK tool)

Once you have the C# wrapper class for your C++ class ready, it is easy to implement ICustomMarshaler so that you can marshal the C++ object from .NET.

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

于 2013-04-15T03:34:17.597 回答
0
    [DllImport("external.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
    public static extern MbStatus queue_accept(
        int reader,
        [MarshalAs(UnmanagedType.LPStr)] string status);

查找 DllImport 属性的参数。根据您的 DLL,这些可能需要调整!

旁注:我通常将外部 dll 包装在接口和代码层中,以将其解耦以进行测试并使用依赖注入加载它。我也不会更改命名约定。

public interface IExternalDllInterop
{
    MB_STATUS queue_accept(int reader, string status);
}

public class AmbInterop : IAmbInterop
{
    public MbStatus queue_accept(int reader, string status)
    {
        return StaticAmbInterop.mb_queue_accept(reader, message, status);
    }
}
于 2012-06-29T05:56:41.937 回答