前段时间公司做了个winform程序,需要调用c 的dll去读取卡号的程序,期间遇到些问题,下面来分享下

   一、dll路径问题

    相信很多开发者都会遇到这个问题,我总结了下我现在有3总方式去解决这个问题;

1.直接放在bin下面,跟exe文件在同一文件夹下,

ps:调试代码的时候,如果是debug模式的话,就放bin/debug下,同理release 模式就放bin/debug下;如果这种方式不行的话,就试试第二种方式。

2.放在C:\Windows\System32下;

3.如果以上方式都不行的话就,那就只能写物理路径了。例

[System.Runtime.InteropServices.DllImportAttribute(@"E:\Source\GPTagReaderDll", EntryPoint = "OpenPort", CallingConvention = CallingConvention.Cdecl)]
[return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
public static extern bool OpenPort(string pPortname, uint dBaud);

该种方式只适合调一个dll的方式,如果调用的这个dll依赖于其他的dll的话这种方式是行不通的;这种方式还有局限性,如果发布出去,你得要求别人的机子上这个物理路径下必须有这个文件,但是 这个太不现实了

除这3种方式外,还听说过写到环境变量里,不过这种方式没试过,就不在此提了。

二、类型转换的问题

下面是c的结构体:

typedef struct
{
unsigned char DeviceIdentify[30];//Greenpow Usb IC card reader
unsigned short res;
}FindDeviceAck_Struct;

我们需要把它转换成c#的结构体:

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential,
CharSet = System.Runtime.InteropServices.CharSet.Ansi,Pack =1)]
public struct FindDeviceAck_Struct
{ /// unsigned char[30]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr,
SizeConst = 30)]
public string DeviceIdentify; /// unsigned short
public ushort res;
}

c# 跟c/c++类型的对应方式,可参考http://www.cnblogs.com/ausoldier/archive/2007/12/07/986141.html;

我这里DeviceIdentify用String接收,但是出现了乱码,后来改成了

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential,
CharSet = System.Runtime.InteropServices.CharSet.Ansi,Pack =1)]
public struct FindDeviceAck_Struct
{ /// unsigned char[30]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst = 30)]
public byte[] DeviceIdentify; /// unsigned short
public ushort res;
}

string 对应的是ByValTStr,byte[] 对应的是ByValArray,sizeconst指的是大小,pack=1表示按1字节对齐

三、调用c里的方法

  c里的方法是BOOL FindDevice(FindDeviceAck_Struct &finddeviceack);

刚开始我直接这样写,

        [System.Runtime.InteropServices.DllImportAttribute("GPTagReaderDll", EntryPoint = "FindDevice", CallingConvention = CallingConvention.Cdecl)]
public static extern bool FindDevice(FindDeviceAck_Struct finddeviceack);

调用的时候

 FindDeviceAck_Struct findDeviceAck=new FindDeviceAck_Struct();
var result= NativeMethods.FindDevice(findDeviceAck);

结果报了下面这个错误:尝试读取或写入受保护的程序。通常指示其他内存已经存在。

    后来同事提醒才注意到BOOL FindDevice(FindDeviceAck_Struct &finddeviceack)参数&finddeviceack 有个'&'。

经改成

        [System.Runtime.InteropServices.DllImportAttribute("GPTagReaderDll", EntryPoint = "FindDevice", CallingConvention = CallingConvention.Cdecl)]
public static extern bool FindDevice(ref FindDeviceAck_Struct finddeviceack);

这样就调用成功了

关于c#调用c/c++ dll遇到的问题总结的更多相关文章

  1. 调用Interop.zkemkeeper.dll无法使用解决方案

    调用Interop.zkemkeeper.dll无法使用 已经注册dll成功但是还是报错 检索 COM 类工厂中 CLSID 为 {00853A19-BD51-419B--2DABE57EB61F} ...

  2. c# 传递Null的string值导致的调用C++的dll报错 Attempted to read or write protected memory.

    c# 调用C++的dll报错 Attempted to read or write protected memory:   原因是:c# 传递Null的string值导致的,将Null改为string ...

  3. Node调用C++(dll)

    最近开始搞毕设了,打算用自己拿手的js来搞,但是仿佛入坑了,Node还不是很熟.总之,兵来将挡,水来土掩嘛,带着问题学习才是最高效的. 折腾1:Node 调用 C++ 刚开始,虽然我老师把dll文件给 ...

  4. golang调用c++的dll库文件

    最近使用golang调用c++的dll库文件,简单了解了一下,特作此笔记:一.DLL 的编制与具体的编程语言及编译器无关 dll分com的dll和动态dll,Com组件dll:不管是何种语言写的都可以 ...

  5. vs2010下C++调用lib或dll文件

    注: DLL:表示链接库,包含dll,lib文件: dll: 表示my.dll文件 lib: 表示my.lib文件 C++ 调用.lib的方法: 一: 隐式的加载时链接,有三种方法 1  设置工程的 ...

  6. paip.java c# .net php python调用c++ c dll so windows api 总结

    paip.java c# .net  php python调用c++ c dll so windows api 总结 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来 ...

  7. c++builder调用VC的dll以及VC调用c++builder的dll

    解析__cdecl,__fastcall, __stdcall 的不同:在函数调用过程中,会使用堆栈,这三个表示不同的堆栈调用方式和释放方式. 比如说__cdecl,它是标准的c方法的堆栈调用方式,就 ...

  8. LabView调用C#混合模式dll

    在一些特定要求下,我们的C#可能需要制作dll给LabView进行调用,并且我们不能够保证C#的程序是完全自己写而不调用第三方的dll库.很多时候我们需要使用诸如Sqlite.Net.AForge.N ...

  9. C#调用C++的DLL搜集整理的所有数据类型转换方式

    //C#调用C++的DLL搜集整理的所有数据类型转换方式,可能会有重复或者多种方案,自己多测试 //c++:HANDLE(void *) ---- c#:System.IntPtr //c++:Byt ...

随机推荐

  1. 第一百九十六天 how can I 坚持

    老妈邮的咸菜到了,美味啊,买不到,哈哈. 以后要勤给鱼换水啊,10天不换,水都臭了,拒绝懒惰. 明天要回济南了,刘松结婚,估计又没法发博客了. 两条鱼,一条罗娜,一条我,哈哈. 睡觉.

  2. [翻译]创建ASP.NET WebApi RESTful 服务(8)

    本章讨论创建安全的WebApi服务,到目前为止,我们实现的API都是基于未加密的HTTP协议,大家都知道在Web中传递身份信息必须通过HTTPS,接下来我们来实现这一过程. 使用HTTPS 其实可以通 ...

  3. Javascript函数柯里化(curry)

    函数柯里化currying,是函数式编程非常重要的一个标志.它的实现需要满足以下条件,首先就是函数可以作为参数进行传递,然后就是函数可以作为返回值return出去.我们依靠这个特性编写很多优雅酷炫的代 ...

  4. C#中位、字节等知识

    本文介绍C#中位.字节等知识. 1. 位(bit) 位(bit)有叫做比特,指二进制中的一位,是二进制的最小信息单位. bit也被称作小b,用b表示. 2. 字节(bytes) 8位表示一个字节. 由 ...

  5. 根据路径获得文件名以及Aspose.Cells.dll操作excel 以及使用iTextSharp.text.pdf.PdfReader.dll对PDF的操作

    string result = Regex.Match(str,@"[^\\]+$").Value;//正则表达式 this.listBox1.Items.Add(Path.Get ...

  6. POJ 3254 Corn Fields (状压dp)

    题目链接:http://poj.org/problem?id=3254 给你n*m的菜地,其中1是可以种菜的,而菜与菜之间不能相邻.问有多少种情况. 状压dp入门题,将可以种菜的状态用一个数的二进制表 ...

  7. Web Service实现分布式服务的基本原理

    简单的说, 就是客户端根据WSDL 生成 SOAP 的请求消息, 通过 HTTP 传输方式(也可以是其它传输方式, 如 FTP 或STMP 等,目前 HTTP 传输方式已经成为 J2EE Web Se ...

  8. JSP文件下载时文件名在ie和firefox下面文件名不一致极其超链接中文乱码的问题的改进

    response.setContentType("application/octet-stream;charset=UTF-8"); fileName=java.net.URLEn ...

  9. visual studio 设计器上出现蓝色的点和箭头

    visual studio 设计器上出现蓝色的点和箭头: 突然发现打开visual studio 的时候出现了很多蓝色的点和箭头,解决办法是:按组合快捷键 Ctrl+R,Ctrl+W 或 Ctrl+E ...

  10. 【原创】[PS技巧]如何制作翘角纸条的阴影效果

    (从已经死了一次又一次终于挂掉的百度空间人工抢救出来的,发表日期 2014-05-19) 在网页设计中经常会用到翘角纸条的效果.如:百度空间首页: pic.1 下面我详细讲解一下这个效果使用PS如何制 ...