这里讲C#调用C++的类,也是我真正想要的做的。网上关于这方面的知识挺杂,我折腾了好久终于搞定了。
大致有两种方法。第一种C#直接调,用到System.Runtime.InteropServices中的Marshal类,貌似这样可能通过直接操纵内存来实现调用,但我没有尝试;第二种方法是用managed C++包装native C++,然后供C#调用。这里详细讲一下这种方法,并基本考虑到了所有的情况。
1 // nativecpp.h 2 // nA不是C#调用对象,nB是,但nB中用到了nA类 3 class __declspec( dllexport ) nA //有人提醒我__declspec( dllexport )可以加在方法前面,//但不要加在类前面,否则会出现问题.但我去掉后编译就出错了。 4 { 5 char * Ama; 6 int Afoo(); 7 }; 8 // nB基本已经涵盖了所有的情况 9 class __declspec( dllexport ) nB 10 { 11 nA Bma; 12 int Bmb; 13 nA BmArr[]; 14 bool Bfoo( char * a, nA[] b); //假设主要想调用这个函数,则包装时只要包装这个即可 15 };
用managed C++包装。在vs2008中建工程时选CLR Class Library即可。添加对上面生成的nativecpp.dll的引用。这里我的引用采用了C#的add reference的形式,而不是传统C++在linker中添加.lib的方式。
1 #include " nativecpp.h " 2 using namespace System; 3 4 namespace managecpp{ 5 public ref class mA 6 { 7 private : 8 nA * aptr; 9 public : 10 mA(): aptr( new nA()) {} 11 ~ mA() { delete aptr; } 12 nA getA() 13 { 14 return * aptr; 15 } 16 }; 17 public ref class mB 18 { 19 private : 20 nB * bptr; 21 public : 22 mB(): bptr( new (nB) ) {} 23 ~ mB() { delete bptr; } 24 bool mBoo( System::String ^ a, array < mA ^> ^ b, int count) // 数组的包装,//这里'^'的含义我不太明白,这里a, b都是指针 25 { 26 // string转成char* 27 cli::array < wchar_t, 1 > ^ aArr = a -> ToCharArray(); 28 const int nLength = aArr -> Length; 29 char * ap = new char [nLength + 1 ]; 30 for ( int x = 0 ; x < nLength; ++ x) 31 { 32 ap[x] = static_cast < char > (apArr[x]); 33 } 34 ap[nLength] = 0 ; 35 // array<mA>转成mA[] 36 mA * newb = new mA[count]; 37 for ( int i = 0 ; i < count; i ++ ) 38 { 39 newb[i] = b -> getA(); 40 } 41 bool rel = bptr -> nBfoo(ap, newb); 42 delete[] aArr; 43 delete[] newb; 44 return rel; 45 } 46 }; 47 }
剩下的是c#调用的代码。首先要添加对managecpp.dll的引用,另外要将nativecpp.dll拷贝到bin目录下(无法理解)。
1 namespace cscallcpp 2 { 3 public class csB 4 { 5 bool csBoo(String a, csA[] b) 6 { 7 mB mb = new mB(); 8 return mb.mBoo(a, b); //实例化后正常调用即可 9 } 10 } 11 }
我主要纠结的是在native c++中定义的类型的数组如何包装的问题,最后采用的方法比较挫,又创建了一个数组,然后赋值,这在空间、效率上都不咋的。请高人赐教。
转自:http://www.cnblogs.com/cdbean/archive/2011/01/30/1947616.html