前段时间公司做了个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. [转]Torch是什么?

    Torch是一个广泛支持机器学习算法的科学计算框架.易于使用且高效,主要得益于一个简单的和快速的脚本语言LuaJIT,和底层的C / CUDA实现:Torch | Github 核心特征的总结:1. ...

  2. JAVA大数运算

    java大数是个好东西,用起来方便,代码短. 代码如下: import java.util.*; import java.math.*; public class Main { public stat ...

  3. POJ 1160Post Office

    POJ 1160    Post Office 我不知道优化,我只知道最暴力的方法,O(V^3),居然100ms不到的过了 设DP[i][j][k]表示考虑前i个小镇,放了j个邮局,最后一个邮局的所在 ...

  4. UVaLive 6698 Sightseeing Bus Drivers (水题,贪心)

    题意:n个工人,有n件工作a,n件工作b,每个工人干一件a和一件b,a[i] ,b[i]代表工作时间,如果a[i]+b[j]>t,则老板要额外付钱a[i]+b[j]-t;现在要求老板付钱最少: ...

  5. MyArrayList——实现自己的ArrayList!

    注:转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5965205.html ArrayList是我们常用的集合类之一,其实它的实现机制很简单,底层还是使用了一个 ...

  6. Linux 基本权限(一)

    1. 权限概念 root@hang:/home# ll 总用量 20#文件权限 链接数量 文件所有者 所属用户组 容量大小B 创建(修改)时间 文件名 drwxr-xr-x root root 11月 ...

  7. 【转】Android图片加载神器之Fresco-加载图片基础[详细图解Fresco的使用]

    Fresco简单的使用—SimpleDraweeView 百学须先立志—学前须知: 在我们平时加载图片(不管是下载还是加载本地图片…..)的时候,我们经常会遇到这样一个需求,那就是当图片正在加载时应该 ...

  8. cvc-complex-type.2.4.a: Invalid content was found starting with element

    在写xml的时候又一次总是报cvc-complex-type.2.4.a: Invalid content was found starting with element 错误,还出现小红叉,在网上找 ...

  9. SoapUI命令行方式运行

    http://stackoverflow.com/questions/9220132/soapui-groovy-script-calls-to-command-line SoapUI支持用命令行方式 ...

  10. Codeforces Gym 100231L Intervals 数位DP

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description Start with an integer, N0, ...