程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 關於c#調用c/c++ dll遇到的問題總結

關於c#調用c/c++ dll遇到的問題總結

編輯:關於C++

關於c#調用c/c++ dll遇到的問題總結

前段時間公司做了個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);

這樣就調用成功了

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved