none
(关于C++/CLI与COM)要怎样做才能在C#中自由引用非托管C++类 RRS feed

  • 问题

  • 我想在C#(.NET 4.0)环境下引用C++6.0的类 因为涉及到类 所以DLLImport不好使 比较常见的解决办法还剩C++/CLI和COM两种

    p.s 我的非托管C++API只有头文件的代码 没有实现的代码(只有库) 

    我的问题

    1. 是不是我这种情况没办法用C++/CLI来实现(因为没有实现的代码)?

    2. 如果用COM实现的话 还有几个问题 比如一个类A 在他的类方法里要传一个类B的对象作为参数时 这种情况该如何处理? 是不是我还要去包装类B 直到方法里包含的都是原生数据类型为止 然后再一层一层的构造/调用?

    3. 方法的返回值是自定义类时又该如何处理?

    4. 前面的typedef如何处理?

    // 某个我需要用到的头文件片段
    // 包含一些其他的头文件
    
    class DtBackendMap;
    class DtVrfConfigurationFileComposer;
    class DtIfServerRequestResponse;
    
    typedef void (*DtScenarioCallbackFcn)(void* usr);
    class DtVrfOverlayObjectModify;
    
    typedef void (*DtBackendSaveCallbackFcn)
       (const DtSimulationAddress& addr, DtSaveResult result, void * usr);
    
    class DtVrfRemoteController
    {
    public:
    
       DtVrfRemoteController();
    
       virtual void init(DtExerciseConn* exConn);
       virtual void init(DtVrfMessageInterface* msgIf);
    
       virtual ~DtVrfRemoteController();
    
       virtual DtVrfMessageInterface* vrfMessageInterface() const;
    
       virtual const DtSimulationAddress& simulationAddress() const;
    
       virtual const DtList& backends() const;
    }



    • 已编辑 misami 2012年12月7日 3:15
    2012年12月7日 2:43

答案

  • 你好,

    欢迎来到这里。

    1. 是不是我这种情况没办法用C++/CLI来实现(因为没有实现的代码)?

    没有实现代码的话,只能自己重写实现部分。或者反编译DLL,但这个比较麻烦。

    1. 如果用COM实现的话 还有几个问题 比如一个类A 在他的类方法里要传一个类B的对象作为参数时 这种情况该如何处理? 是不是我还要去包装类B 直到方法里包含的都是原生数据类型为止 然后再一层一层的构造/调用?

    这里我给您举个例子:

    #include <iostream>
    
    using namespace std;
    
    class MyClassA
    {
    public:
    	MyClassA();
    	~MyClassA();
    	int FuncA();
    	int a;
    };
    
    MyClassA::MyClassA()
    {
    	cout<<"Construnction of MyClassA"<<endl;
    }
    
    MyClassA::~MyClassA()
    {
    	cout<<"Destrunction of MyClassA"<<endl;
    }
    int MyClassA::FuncA()
    {
    	cin>>a;
    	cout<<"Your input a is "<<a<<endl;
    	return a;
    }
    
    class MyClassB
    {
    public:
    	MyClassB(MyClassA &a1);
    	~MyClassB();
    
    };
    
    MyClassB::MyClassB(MyClassA &a2)
    {
    	cout<<"Construnction of MyClassB"<<endl;
    	cout<<"The Member 'a' of MyClassA is "<<a2.a<<endl;
    }
    
    MyClassB::~MyClassB()
    {
    	cout<<"Destrunction of MyClassB"<<endl;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	MyClassA *a3 = new MyClassA;
    	a3->FuncA();
    	MyClassB * b1 = new MyClassB(*a3);
    	delete a3;
    	delete b1;
    	return 0;
    }
    1. 方法的返回值是自定义类时又该如何处理?

    这个我建议您传地址指针。

    1. 前面的typedef如何处理?

    没太明白您的意思,这个方法是把typedef void (*DtScenarioCallbackFcn)(void* usr);中的DtScenarioCallbackFcn用另一个称号usr作为等价名称。既:DtScenarioCallbackFcnusr表示同一个方法的两种叫法。

    希望我的回复对您有帮助。

    此致


    Elegentin Xie
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 misami 2012年12月12日 1:51
    2012年12月11日 7:04
    版主
  • 你的导入库指的是什么? LIB 吗?如果是 LIB ,那么在C++中,可以通过静态链接的方式(早绑定)来使用。当然此方法在.NET中无效。

    如果你有.H和.DLL,那么你只能使用晚绑定模式,在.NET中,你可以使用DllImport,或者Win API(先用DllImport引入LoadLibrary ,FreeLibrary等API,然后采用“晚绑定”的模式调用)。

    关于使用DllImport使用非托管导出类的具体方式和注意点,我找到了一篇文章,你可以仔细阅读下:

    http://blog.163.com/marje@126/blog/static/64422578201101411239332/

    我再补充一个有用的工具:depends.exe ,查找DLL导出方法和类的好工具。

    同时:如果你的导出类只是简单的数据结构,而不包含导出方法,那么结果会更简单。

    2012年12月12日 6:44

全部回复

  • 你好,

    欢迎来到这里。

    1. 是不是我这种情况没办法用C++/CLI来实现(因为没有实现的代码)?

    没有实现代码的话,只能自己重写实现部分。或者反编译DLL,但这个比较麻烦。

    1. 如果用COM实现的话 还有几个问题 比如一个类A 在他的类方法里要传一个类B的对象作为参数时 这种情况该如何处理? 是不是我还要去包装类B 直到方法里包含的都是原生数据类型为止 然后再一层一层的构造/调用?

    这里我给您举个例子:

    #include <iostream>
    
    using namespace std;
    
    class MyClassA
    {
    public:
    	MyClassA();
    	~MyClassA();
    	int FuncA();
    	int a;
    };
    
    MyClassA::MyClassA()
    {
    	cout<<"Construnction of MyClassA"<<endl;
    }
    
    MyClassA::~MyClassA()
    {
    	cout<<"Destrunction of MyClassA"<<endl;
    }
    int MyClassA::FuncA()
    {
    	cin>>a;
    	cout<<"Your input a is "<<a<<endl;
    	return a;
    }
    
    class MyClassB
    {
    public:
    	MyClassB(MyClassA &a1);
    	~MyClassB();
    
    };
    
    MyClassB::MyClassB(MyClassA &a2)
    {
    	cout<<"Construnction of MyClassB"<<endl;
    	cout<<"The Member 'a' of MyClassA is "<<a2.a<<endl;
    }
    
    MyClassB::~MyClassB()
    {
    	cout<<"Destrunction of MyClassB"<<endl;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	MyClassA *a3 = new MyClassA;
    	a3->FuncA();
    	MyClassB * b1 = new MyClassB(*a3);
    	delete a3;
    	delete b1;
    	return 0;
    }
    1. 方法的返回值是自定义类时又该如何处理?

    这个我建议您传地址指针。

    1. 前面的typedef如何处理?

    没太明白您的意思,这个方法是把typedef void (*DtScenarioCallbackFcn)(void* usr);中的DtScenarioCallbackFcn用另一个称号usr作为等价名称。既:DtScenarioCallbackFcnusr表示同一个方法的两种叫法。

    希望我的回复对您有帮助。

    此致


    Elegentin Xie
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 misami 2012年12月12日 1:51
    2012年12月11日 7:04
    版主
  • 我先申明一点:在使用导出类上,COM不会比DllImport更简单。

    事实上你应该区分早绑定和晚绑定,DllImport 同晚绑定相似,而COM可以使用早绑定或晚绑定来引用第三方DLL。因此,如果仅仅是因为导出类的问题,我可以明确的告诉你,如果采用晚绑定,编写COM的难度不输于 DllImport(你提的问题2,3已经触及这个问题),除此之外,你还需要注册(还需要考虑UAC),你还需要考虑如何部署互操作程序集。

    2012年12月12日 1:34
  • 非常感谢您的回复
    2012年12月12日 1:56
  • 谢谢您的回复

    请问我这个C++6.0的API(只有头文件, 导入库, 和dll, 没有实现(cpp)) 可以通过dllimport在.NET里用么 麻烦详细的说一下怎样使用dllimport来处理类方法

    2012年12月12日 2:09
  • 你的导入库指的是什么? LIB 吗?如果是 LIB ,那么在C++中,可以通过静态链接的方式(早绑定)来使用。当然此方法在.NET中无效。

    如果你有.H和.DLL,那么你只能使用晚绑定模式,在.NET中,你可以使用DllImport,或者Win API(先用DllImport引入LoadLibrary ,FreeLibrary等API,然后采用“晚绑定”的模式调用)。

    关于使用DllImport使用非托管导出类的具体方式和注意点,我找到了一篇文章,你可以仔细阅读下:

    http://blog.163.com/marje@126/blog/static/64422578201101411239332/

    我再补充一个有用的工具:depends.exe ,查找DLL导出方法和类的好工具。

    同时:如果你的导出类只是简单的数据结构,而不包含导出方法,那么结果会更简单。

    2012年12月12日 6:44