如何在C#中使用C ++接口?

时间:2014-10-15 06:37:14

标签: c# c++ .net interop

为了隐藏函数的实现,我通常编写以下C ++代码并将我的函数公开为'interfaces'

// the interface to expose
class ICalcService
{
public:
    virtual double Multiple(double a, double b) const = 0;
};

// the implementation of the interface
class CalcService final : public ICalcService
{
    virtual double Multiple(double a, double b) const override
    {
        return a * b;
    }
};

// expose the 'CreateCalcService' to mydll.dll as C function 
extern "C" __declspec(dllexport) void CreateCalcService(void** obj)
{
    *obj = new CalcService();
}

C ++中的典型用法是

// typical way to consume the interface in C++
void test_cpp_code()
{
    ICalcService* calc;
    CreateCalcService(reinterpret_cast<void**>(&calc));
    cout << calc->Multiple(15, 23) << endl;
}

现在我想用C#代码来消费它。经过一段时间的研究,我写了下面的代码

using System.Runtime.InteropServices;
class Program
{
    interface ICalcService
    {
        double Multiple(double a, double b);
    }

    [DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
    private extern static void CreateCalcService(out object obj);

    static void Main(string[] args)
    {
        object o;
        CreateCalcService(out o);
        var calc = o as ICalcService;
        calc.Multiple(14, 29);
    }
}

但它不会像我预期的那样工作。相反,异常是在CreateCalcService(out o)行抛出。

托管调试助手'InvalidVariant'在'xx \ xx \ myloader.vshost.exe'中检测到问题。 附加信息:在从非托管VARIANT到托管对象的转换过程中检测到无效的VARIANT。将无效的VARIANT传递给CLR可能会导致意外的异常,损坏或数据丢失。 如果存在此异常的处理程序,则可以安全地继续该程序。 myloader.exe中出现未处理的“System.Runtime.InteropServices.InvalidOleVariantTypeException”类型异常 附加信息:指定的OLE变体无效。

有人可以让我知道这是什么问题以及如何使其发挥作用?例如错误的C#dllimport签名。

提前致谢!

3 个答案:

答案 0 :(得分:0)

不,你不能直接调用这样的C ++接口。有几种选择。

1)用C语言包装C ++代码。

// expose the 'CreateCalcService' to mydll.dll as C function
extern "C" __declspec(dllexport) void CreateCalcService(void** obj)
{
    *obj = new CalcService();
}

extern "C" __declspec(dllexport) double Multiple(void* obj, double a, double b)
{
    ICalcService calc = (ICalcService)obj;
    calc->Multiple(a, b);
}

使用C#代码:

[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private extern static void CreateCalcService(out IntPtr obj);

[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private extern static double Multiple(IntPtr obj, double a, double b);

static void Main(string[] args)
{
    IntPtr calc;
    CreateCalcService(out handle);
    Multiple(calc, 14, 29);
}

2)编写C ++ / CLI包装器。

答案 1 :(得分:0)

它无效。 C ++接口(只是class)与C#interface不同。您不能将C ++对象的实例类型转换为C#接口。

答案 2 :(得分:0)

private extern static void CreateCalcService(out object obj);

param是错误的,它不能是object.Try the byte []。比如

byte[] mac = new byte[16];
private extern static void CreateCalcService(mac);