当对c++几种调用方式有了解以后我们可以试着写个c++动态连接库了,我们现在来写个简单的c++求和函数并把它封装成dll,供以后的c#调用

我们写dll的时候,个人认为,要写就要把dll写好,写标准,别的地方才能用得方便,接下来就带你们写个标准的dll

第一步,确定你要写哪些方法,根据这些方法我们创建一个头文件,我这边主要写个add();

例子如下:head.h

#ifdef api
#else
#define api extern "C" _declspec(dllimport)
#endif api int _stdcall add(int a,int b);

第二步:写函数主体部分add.dll

#define api extern "C" _declspec(dllexport)

#include "head.h"
#include "windows.h" int _stdcall add(int a,int b)
{
return a+b;
}

第三步:定义输出函数名文件 add.def(此文件先创建再添加到工程)

LIBRARY add/*这个名字要和输出dll名字一致*/
EXPORTS
add

编译连接,在debug目录下就可以找到生成的dll啦!

接下来我们开始在c#中调用这个dll

 [DllImport("RFDLL.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int add(int a, int b); public void ProjectMethod()
{
MessageBox.Show("5+5="+add(5,5).ToString());
}

到此,最简单最标准的dll调用就完成啦!

在调用c++过程中,你会遇到很多莫名的错误,像堆栈不对称错误是很多新手最容易犯错的,下面我就简单说说这类问题怎么解决

从.NET1.1升级到.NET2.0时出现的PInvokeStackImbalance错误
微软官方的解释(http://msdn2.microsoft.com/zh-cn/library/0htdy0k3.aspx)
如果 CLR 检测到平台调用之后的堆栈深度与 DllImportAttribute 属性指定的调用约定中以及托管签名的参数声明中提供的预期堆栈深度不匹配,则将激活 PInvokeStackImbalance 托管调试助手 (MDA)。
下面将举一个具体的例子
PCCamera类(UserLib.Device.PCCamera摄像头类)在从.NET1.1升级到.NET2.0时出现的PInvokeStackImbalance错误:
检测到 PInvokeStackImbalance
Message: 对 PInvoke 函数“WindowsApplication1!UserLib.Device.PCCamera::SendMessage”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。
错误首次发生在这一行代码: SendMessage(hWndC, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0);
经过分析发现所有调用SendMessage函数的地方都会出现以上错误
于是查看DLLImport:
[DllImport("User32.dll")]
private static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, long lParam);
原来是因为WinAPI的long类型是32位的,而C#的long是64位的,这就导致堆栈不对称,引发错误.
在.NET2.0中加入了MDA(managed debugging assistant), 在平台调用时后会检查栈的指针, 如果发现不平衡, 就会抛出PInvokeStackImbalance异常; 而在.NET1.1中不会检查, 所以不会捕获到异常, 但在运行时会导致不稳定.
解决方法:
将最后一个”long lParam” 改为 “int wParam”, 因为C#中int是32位的. 并且将之后有涉及到SendMessage函数的参数适当地转成int型就可以了.
但是, 之后查阅了资料发现先前的解决方案还有不合适的地方, 应该将其中的 ”wParm” 和 ”lParm” 参数的类型都转成IntPtr类型,并且将后面涉及到的参数的 ”0” 改为 “IntPtr.Zero”. 因为如果使用int类型,那么这段代码在64位的Windows上面将会无法正常运行.
总结:
我们在调用WinAPI时要特别小心, 因为WinAPI和C#的数据类型不是完全一样, 就好像在WinAPI中的long类型在C#中就是int类型, 如果没有处理好类型问题, 就很可能会导致堆栈的不平衡,引发PInvokeStackImbalance错误, 但是这类错误在.NET1.1下不会被暴露出来, 所以在从.NET1.1升级到.NET2.0时要特别注意此类问题.

c#调用c++ dll(二)的更多相关文章

  1. c# 调用c++dll二次总结

    1.pinvoke结构不对称,添加语句(网上有) 2.含回调函数,成员参数的结构体必须完全,尽管自己用不到. 3.加深对c++指针的理解.一般情况下,类型加*等效于c++中的ref.但对于short* ...

  2. c# 调用c++DLL方法及注意事项

    引用命名空间 using System.Runtime.InteropServices 调用方法: 一.静态加载 用DllImprot方式来加载c++DLL.如下格式: //对应c++方法 //voi ...

  3. 【JNI】OPUS压缩与解压的JNI调用(.DLL版本)

    OPUS压缩与解压的JNI调用(.DLL版本) 一.写在开头: 理论上讲,这是我在博客园的第一篇原创的博客,之前也一直想找个地方写点东西,把最近做的一些东西归纳总结下,但是一般工程做完了一高兴就把东西 ...

  4. Native Application 开发详解(直接在程序中调用 ntdll.dll 中的 Native API,有内存小、速度快、安全、API丰富等8大优点)

    文章目录:                   1. 引子: 2. Native Application Demo 展示: 3. Native Application 简介: 4. Native Ap ...

  5. C#调用VC dll输出参数

    最近做项目需要把以前Vc写的程序整合到VS2005来,用c#写的,以前VC的动态连接库写好了,重写比较麻烦,让C#调用VC dll就好了.但碰到了一个问题:VC中作为输出参数的char*类型的变量应该 ...

  6. 巧用C#做中间语言 实现Java调用.net DLL

    本文将详细为大家介绍一个java调用.net DLL的方法,以实现特殊的客户的特殊要求:“在Java项目中必须使用其提供的用.net写的DLL加密机制!” 环境与工具: ◆.net framework ...

  7. C# 调用外部dll(转)

    C# 调用外部dll   一.      DLL与应用程序 动态链接库(也称为DLL,即为"Dynamic Link Library"的缩写)是Microsoft Windows最 ...

  8. C#调用外部DLL介绍及使用详解

    一.      DLL与应用程序 动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要的组成要素之一,打开Windows系统文件 ...

  9. SOE 中调用第三方dll

    一.简介 在利用soe实现server的扩展的时候,有些时候,需要调用第三方的dll库.官网中给出了明确的说明,soe中是可以添加第三方的dll文件,但是一直没有测试.按照官方的步骤应该是一个非常的简 ...

随机推荐

  1. Gym 100827G Number Game (博弈)

    Number Game Alice and Bob are playing a game on a line of N squares. The line is initially populated ...

  2. 搭建Discuz! (mysql+apache+Discuz! )

    0. 配置环境 0.0 安装apache 0.1 安装php 1.数据库准备 1.1 创建数据库用户 1.2 创建discuz使用的数据库(编码:utf8-general-ci) 1.3 把1.2创建 ...

  3. [iOS基础控件 - 6.5] UITableView的数据刷新

    A.需求 1.以LOL英雄列表为蓝本,给其加上实时修改英雄名称的功能 2.使用UIAlertView 3.全局刷新reloadData 4.局部刷新     B.实现 1.使用UIAlertView ...

  4. Visual Studio中的Build Event

    在VS中,进行build时,可以在build之前,或者之后执行一些操作,比如把一些css,font,images文件从一个项目的文件夹复制到另一个项目的文件夹 方法: 点击项目,右键-属性-Build ...

  5. Articulate Studio课间制作工具

    Articulate Studio可以说是目前国际上用户最广泛的e-learning课件制作工具之 一,通过Articulate Studio,你可以方便.快捷的创建引人入胜的Flash演示和e-le ...

  6. iOS多线程拾贝------操作巨人编程

    iOS多线程拾贝------操作巨人编程 多线程 基本 实现方案:pthread - NSThread - GCD - NSOperation Pthread 多平台,可移植 c语言,要程序员管理生命 ...

  7. spring读书笔记----Quartz Trigger JobStore出错解决

    将Quartz的JOBDetail,Trigger保持到数据库的时候发现,系统报错 The job (DEFAULT.jobDetail) referenced by the trigger does ...

  8. mysql之select+五种子句的理解

    select 可以包含很复杂,很丰富的逻辑,最能考验一个人的逻辑思维能力和sql语句的掌握程度,我是这么认为,以前的很多次面试几乎都死在它手上,所以才有了今天的这篇日志,下定决心把它学好. where ...

  9. Ubuntu字体设置

    Ubuntu所带的字体不是很好看,比较模糊,现修改为微软雅黑 Win7安装分区下的 \windows\fonts\文件夹下,复制msyh.ttf和msyhhd.ttf到/home/m/msfonts文 ...

  10. nginx,linux压力测试工具webbench

    webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便. 1.适用系统:Linux 2.编译安装: 1. wget htt ...