码迷,mamicode.com
首页 > 编程语言 > 详细

关于c#调用c/c++ dll遇到的问题总结

时间:2016-07-08 13:21:44      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:

  前段时间公司做了个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遇到的问题总结

标签:

原文地址:http://www.cnblogs.com/wufanghai-engineer/p/5652830.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!