在c#中调用c++里导出的DLL之相关说明

来源:互联网 发布:淘宝买家信誉怎么刷 编辑:程序博客网 时间:2024/05/16 06:31

一般我们会有这样一种情况,函数由c++来写,在c#里调用这一函数。这一要求是因为,同样地代码,c++的运行速度比c#运行速度快。

比如说,我们使用OpenCV获取摄像机图像,在xna中显示出来。

在c++中函数导出的代码这样写:

extern "C" __declspec(dllexport) bool  __stdcall GetImg(byte imgData[]){if (cvGrabFrame(capture1)){img1=cvRetrieveFrame(capture1);int height = img1->height;int width = img1->width;for (int j = 0; j < height; j++){for (int i = 0; i < width; i++){imgData[(i + j * width)*4 + 0] =  (byte)(img1->imageData + img1->widthStep * j)[3 * i + 0];imgData[(i + j * width)*4 + 1] =  (byte)(img1->imageData + img1->widthStep * j)[3 * i + 1];imgData[(i + j * width)*4 + 2] = (byte)(img1->imageData + img1->widthStep * j)[3 * i + 2];imgData[(i + j * width)*4 + 3] = 255;}}return true;}else{return false;}}
我们一一来解释:

一: extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。让我们来详细解读这两重含义。

1.  extern在c++语言里是全局变量的意思,如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int fun(int mu),那么就可以在a.c中声明extern int fun(int mu),然后就能使用fun来做任何事情。就像变量的声明一样,extern int fun(int mu)可以放在a.c中任何地方,而不一定非要放在a.c的文件作用域的范围中。

2.  被extern "C"修饰的变量和函数是按照C语言方式编译和连接的;

一般来说在DLL的设计中中,如果使用C++开发,通常在导出函数的定义中使用extern "C",为什么呢?因为当用户使用"运行时动态链接"的时候将使用GetProcAddress函数得到导出函数的地址,该函数是通过导出函数的函数名定位导出函数的,而C++编译器会对开发者定义的函数名进行修饰,导致导出表中的函数名通常不是开发者使用的函数名,比如函数ExportedFn可能被修饰成??ExportedFn@QAEX。所以使用extern "C"通知编译器按照C的格式进行编译,而不是使用C++的方法进行编译。


二:  __declspec(dllexport)

声明一个导出函数,是说这个函数要从本DLL导出。我要给别人用。一般用于dll中
省掉在DEF文件中手工定义导出哪些函数的一个方法。当然,如果你的DLL里全是C++的类的话,你无法在DEF里指定导出的函数,只能用__declspec(dllexport)导出类


三: __stdcall

__stdcall是函数调用约定的一种,函数调用约定主要约束了两件事:

  1.参数传递顺序
  2.调用堆栈由谁(调用函数或被调用函数)清理

__stdcall表示

  1.参数从右向左压入堆栈
  2.函数被调用者修改堆栈
  3.函数名(在编译器这个层次)自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸
  如果不用__stdcall修饰函数,在vs2010的c#里调用此DLL会出现函数签名不匹配的错误。


在c#里调用DLL这样写:

[DllImportAttribute("OpenCV2010.dll", CharSet = CharSet.Auto, EntryPoint = "BegainCamera")]        public static extern bool BegainCamera(ref Int32 outWidth, ref Int32 outHeight, Int32 preWidth, Int32 preHeight, Int32 devcieNumber);        [DllImportAttribute("OpenCV2010.dll")]        public static extern bool GetImg(byte[] imgData);        [DllImportAttribute("OpenCV2010.dll")]        public static extern void EndCamera();

声明了之后,c++写得函数就能在c#中调用了。。