标签:
前段时间公司做了个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);
这样就调用成功了
标签:
原文地址:http://www.cnblogs.com/wufanghai-engineer/p/5652830.html