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

一般我们会有这样一种情况,函数由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#中调用了。。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值