非托管C ++ DLL从C#获取结构

时间:2018-12-18 13:07:09

标签: c# c++

是否可以从c ++ DLL调用c#中的方法?

我与C#的沟通良好-> C ++,但是我希望能够发起呼叫C ++-> c#来轮询一些数据

我的代码看起来像这样...

host.h

/*
define the exporter for the C API
*/
#ifdef DLL_EXPORT
#define DLL_EXPORT __declspec(dllexport) 
#else
#define DLL_EXPORT __declspec(dllimport) 
#endif
class myClass
{
public:
    myCLass(){
        //do some initialising
    }
    ~myCLass(){
        //do some tidying
    }

    int getInt(int target) {
        switch (target)
        { 
        case 0:
            return someIntValue; 
        case 1:
            return someOtherIntValue;
        default:
            return 0;
        }
    }

   std::string getString(int target) {
        switch (target)
        { 
        case 0:
            return someStringValue;
        case 1:
            return someOtherStringValue;
        default:
            return "";
        }
    }
}

extern "C" {
    DLL_EXPORT  myClass* myClassConstructor();
    DLL_EXPORT void DestroySpatialser(const myClass* _pContext);
    DLL_EXPORT int getInt(myClass* _pContext, int target);
    DLL_EXPORT void getString(myClass* _pContext, int target, __out BSTR* returnStr);

}

host.cpp

extern "C" {


    myClass* myClassConstructor()
    {
        return new myClass();
    }

    void myClassDestructor(const myClass* _pContext)
    {
        if (_pContext != nullptr)
        {
            _pContext->~myClass();
            delete _pContext;
        }
    }

    //example
    int getInt(myClass* _pContext, int target)
    {
        if (_pContext == nullptr)
        {
            return K_ERR_INT;
        }
        return _pContext->getInt(target);
    }

    void getString(myClass* _pContext, int target, __out BSTR* returnStr)
    {
        std::string str;
        if (_pContext == nullptr)
        {
            str = K_ERR_CHAR;
        }
        else {
            str = _pContext->getString(target);
        }
        const std::string stdStr = str;
        _bstr_t bstrStr = stdStr.c_str();
        *returnStr = bstrStr.copy();
    }
}

csharp.cs

    private const string dllname = "myhost";

    [DllImport(dllname)]
    private static extern IntPtr myClassConstructor();

    [DllImport(dllname)]
    private static extern void myClassDestructor(IntPtr _pContext);

    [DllImport(dllname)]
    private static extern int getInt(IntPtr _pContext, int target);

    [DllImport(dllname)]
    private static extern float getFloat(IntPtr _pContext, int target);

    [DllImport(dllname, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    extern static void getString(IntPtr _pContext, int target, [MarshalAs(UnmanagedType.BStr)] out String str);

    private static IntPtr _pContext;

    public static IntPtr Create()
    {
        _pContext = myClassConstructor();
        Debug.Log("_pContextcreated");
        return _pContext;
    }

    public static void Destroy()
    {
        myClassDestructor(_pContext );
    }

    private static int _getInt(int target)
    {
        return getInt(_pContext , target);
    }

    private static string _getString(int target)
    {
        String str;
        getString(_pContext , target, out str);
        return str;
    }

一切正常。

我想添加从.cs应用程序获取值的功能(它将是3个浮点数的结构),应从myClass实例中调用该值。

我不想在c#端启动此操作(我知道该怎么做)。

有什么建议吗?

编辑

我实施了此处找到的解决方案 https://forum.unity.com/threads/communicating-c-with-c.89930/#post-586885

进行了两次更改(有关原因,请参见下面的评论)

public int whatever = 0;
public delegate int myCallbackDelegate( int n, int m );
private myCallbackDelegate myCallback; // <-- add this line

[DllImport ("DLLImport_CProj")]
private static extern int TakesCallback( myCallbackDelegate fp, int n, int m );

void Awake()
{   
myCallback = new myCallbackDelegate( this.myCallback ) // <-- add this
int resp = TakesCallback(myCallback, 10, 20 ); // <-- change to this 
Debug.Log( resp );
}

2 个答案:

答案 0 :(得分:0)

嗯,我能想到的一种方法是将JSON字符串作为char数组从C ++传递到C#,然后在C#上解析它并获取数据。这是两种语言都熟悉的一种交流方式。 另外,您需要将回调从C#传递到C ++,以允许进行这种操作,如this question中所述。 让我知道这是否有帮助:)

答案 1 :(得分:0)

设置C#类型COMVisible,这意味着您将能够从COM感知的C ++代码中调用它们,例如,使用ATL