<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [C# VS C++] C#代碼遇見了非托管dll如何處理


      ??問題:托管與非托管,兼容?

      • 方法一:DllImport

             現象:托管調試助手 "PInvokeStackImbalance" Message=托管調試助手 "PInvokeStackImbalance":“對 PInvoke 函數“XXXX_Pub_Test!XXXX_Pub_Test.XxxxClient_temp::xxxxclient_config_init”的調用導致堆棧不對稱。原因可能是托管的 PInvoke 簽名與非托管的目標簽名不匹配。請檢查 PInvoke 簽名的調用約定和參數與非托管的目標簽名是否匹配。”

      1. 下面并不能解決問題,只能勉強推送參數??。需要推敲著用

      在DllImport中加入CallingConvention參數就行了,形如以下, 


        [DllImport(xxxx.dll, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]


       DllImport 部分反編譯:

      public class DllImportAttribute: Attribute  
      {  
          public DllImportAttribute(string dllName) {…} //定位參數為dllName  
          public CallingConvention CallingConvention;   //入口點調用約定  
          public CharSet CharSet;                       //入口點采用的字符接  
          public string EntryPoint;                     //入口點名稱  
          public bool ExactSpelling;                    //是否必須與指示的入口點拼寫完全一致,默認false  
          public bool PreserveSig;                      //方法的簽名是被保留還是被轉換  
          public bool SetLastError;                     //FindLastError方法的返回值保存在這里  
          public string Value { get {…} }  
      }
      網上找的說明:
      1、DllImport只能放置在方法聲明上。
      2、DllImport具有單個定位參數:指定包含被導入方法的 dll 名稱的 dllName 參數。
      3、DllImport具有五個命名參數:
         a、CallingConvention 參數指示入口點的調用約定。如果未指定CallingConvention,則使用默認值CallingConvention.Winapi。
         b、CharSet參數指定用在入口點的字符集。如果未指定CharSet,則使用默認值CharSet.Auto。 // CharSet = CharSet.Ansi,試驗用這個
         c、EntryPoint參數給出dll中入口點的名稱。如果未指定EntryPoint,則使用方法本身的名稱。
         d、ExactSpelling參數指示EntryPoint是否必須與指示的入口點的拼寫完全匹配。如果未指定ExactSpelling,則使用默認值false。
         e、PreserveSig參數指示方法的簽名被保留還是被轉換。當簽名被轉換時,它被轉換為一個具有HRESULT返回值和該返回值的一個
         名為retval的附加輸出參數的簽名。如果未指定PreserveSig,則使用默認值true。
         f、SetLastError參數指示方法是否保留Win32“上一錯誤”。如果未指定SetLastError,則使用默認值false。
      4、它是一次性屬性類。
      5、用DllImport屬性修飾的方法必須具有extern修飾符。
      DllImport的用法示例(是用來寫入ini文件的一個win32api):
      #ifdef UNICODE
      #define WritePrivateProfileString  WritePrivateProfileStringW
      #else
      #define WritePrivateProfileString  WritePrivateProfileStringA
      #endif // !UNICODE
      // !UNICODE
      // typedef int                 BOOL;
      WINBASEAPI
      BOOL
      WINAPI
      WritePrivateProfileStringA(
          _In_opt_ LPCSTR lpAppName,
          _In_opt_ LPCSTR lpKeyName,
          _In_opt_ LPCSTR lpString,
          _In_opt_ LPCSTR lpFileName
          );
      [DllImport("kernel32")]
      private static extern long WritePrivateProfileString(string mpAppName,string mpKeyName,string mpDefault,string mpFileName);
      用此方法調用WinAPI的數據類型對應:C++:DWORD(BOOL/*最新*/)--C#:long/int/uint,C++:LPCTSTR(LPCWSTR或LPCSTR)--C#:string。// 解釋和其他不同

      2. dll的位置,看了很多辦法,總結一下:

       DllImport會按照順序自動去尋找的地方: 

      1. 可運行文件exe所在目錄 ,// 用過,用的這個

      2. System32文件目錄 ,// 用過,COM/DCOM注冊的dll最好也放這

      3. 環境變量目錄,// 沒用過

      只需要你把引用的DLL 拷貝到這三個目錄下 就可以不用寫路徑了 或者

      可以這樣server.MapPath(.\bin\*.dll)web中的,同時也是應用程序中的 后來發現用[DllImport(@"C:\OJ\Bin\Judge.dll")]這樣指定DLL的絕對路徑就可以正常裝載。 // [DllImport(@"C:\OJ\Bin\Judge.dll")],用沒成功。其他劃線沒用過

      3. Web 引用第三方非托管dll:

      c#的dllimport使用方法詳解未嘗不是個解決辦法,去里面多了解,簡單總結一下。

       具體做法如下:  

      1. 首先我們在服務器上隨便找個地方新建一個目錄,假如為C:\DLL  

      2. 然后,在環境變量中,給Path變量添加這個目錄  

      3. 最后,把所有的非托管文件都拷貝到C:\DLL中。或者更干脆的把dll放到system32目錄  

      對于可以自己部署的應用程序,這樣未償不是一個解決辦法。然而,如果用的是虛擬空間,是沒辦法把注冊PATH變量或者把我們自己的DLL拷到system32目錄的。同時也不一定知道dll的物理路徑。

      DllImport里面只能用字符串常量,而不能夠用Server.MapPath(@"~/Bin/Judge.dll")來確定物理路徑。ASP.NET中要使用DllImport的,必須在先“using System.Runtime.InteropServices;”不過,我發現,調用這種"非托管Dll”相當的慢,可能是因為我的方法需要遠程驗證吧,但是實在是太慢了。經過一翻研究,終于想到了一個完美的解決辦法,分別取得了LoadLibrary和GetProcAddress函數的地址,再通過這兩個函數來取得我們的DLL里面的函數。

      我們可以先用Server.MapPath(@"~/Bin/Judge.dll")來取得我們的DLL的物理路徑,然后再用LoadLibrary進行載入,最后用GetProcAddress取得要用的函數地址。// 這個類似方法對C#托管dll使用過,動態加載dll,說的不對的請指正

      [DllImport("kernel32.dll")]
      private extern static IntPtr LoadLibrary(String path);
      
      [DllImport("kernel32.dll")]
      private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);
      
      [DllImport("kernel32.dll")]
      private extern static bool FreeLibrary(IntPtr lib);

      //  沒驗證過

      LoadLibrary的裝載和函數調用

      public class DllInvoke 
          {            
              [DllImport("kernel32.dll")] 
              private extern static IntPtr LoadLibrary(String path);
      
              [DllImport("kernel32.dll")]   
              private extern static IntPtr GetProcAddress(IntPtr lib, String funcName); 
      
              [DllImport("kernel32.dll")]     
              private extern static bool FreeLibrary(IntPtr lib);     
      
              private IntPtr hLib;  
       
      
              public DllInvoke(String DLLPath)   
              {           
                  hLib = LoadLibrary(DLLPath);  
              }       
      
              ~DllInvoke()     // 還整出來析構??
              {        
                  FreeLibrary(hLib);  
              }        
      
              //將要執行的函數轉換為委托  
              public Delegate Invoke(String APIName,Type t)     
              {           
                  IntPtr api = GetProcAddress(hLib, APIName);   
                  return (Delegate)Marshal.GetDelegateForFunctionPointer(api,t);     
              }
          }
      LoadLibrary

       下面代碼進行調用 

      // delegate頭頂上是不是也加點什么屬性【】
      //         [...]
                  public delegate int Compile(String command, StringBuilder inf);
                  //編譯
                  DllInvoke dll = new DllInvoke(Server.MapPath(@"~/Bin/Judge.dll"));
                  Compile compile = (Compile)dll.Invoke("Compile", typeof(Compile));
                  StringBuilder inf;
                  compile(@“gcc a.c -o a.exe“,inf);//這里就是調用我的DLL里定義的Compile函數
      View Code

       

      繼續上面的CharSet 

      4. CharSet = CharSet.Ansi

      4. CharSet = CharSet.Ansi才不會報錯。//但不同機器結果可能也不同,難搞哦!

      改為:

      •  [DllImport(xxxx.dll, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
      • 或者[DllImport(xxxx.dll, CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)] // 其他機器報上述錯誤

      System.BadImageFormatException

        HResult=0x8007000B

        Message=試圖加載格式不正確的程序。 (異常來自 HRESULT:0x8007000B)

        Source=XxxxClient_Test

        StackTrace:

         at XXXX_Test.XxxxClient_temp.xxxxclient_init()

         at XxxxClient_Test.Program.Main(String[] args) in C:\Users\*****\source\repos\XXXX_Test\XxxxClient_Test\Program.cs:line 38


       

      5. 非托管dll的回調函數,在托管里如何表示:

      C#默認情況下委托都是stdcall的調用方式,但可以通過UnmanagedFunctionPointer特性來修改

      CallingConvention的值:

          public enum CallingConvention
          {
              Winapi = 1,// 默認平臺調用約定
              Cdecl,     // C調用約定
              StdCall,   // 默認約定,這是使用平臺invoke調用非托管函數的默認約定。
              ThisCall,  // 第一個參數是this指針,僅C++,用于對從非托管 DLL 導出的類調用方法
              FastCall   // 快?
          }

      [UnmanagedFunctionPointer(CallingConvention.Cdecl)]

      public static delegate {callback};

       下面自己寫了一個:

      [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
      public delegate void on_message_back(int cfg, int messageId, string name, IntPtr load, int loadlen, int qos, bool retain);

       用了默認CallingConvention.StdCall,情況是只調用了一次委托,絕無2次。修改為CallingConvention.Cdecl,估計dll是C風格。

      6. .NET版本不支持編碼轉換:

      C# 4.7版之前版本不支持UTF-8 string 編碼,C++ dll使用UTF8編碼,4.7版本支持string轉碼(編碼),string前加MarshalAs(UnmanagedType.LPUTF8Str)。

      解決辦法:自定義UTF8Marshaler

      public class UTF8Marshaler : ICustomMarshaler
          {
              public void CleanUpManagedData(object managedObj)
              {
              }

              public void CleanUpNativeData(IntPtr pNativeData)
              {
                  Marshal.FreeHGlobal(pNativeData);
              }

              public int GetNativeDataSize()
              {
                  return -1;
              }

              public IntPtr MarshalManagedToNative(object managedObj)
              {
                  if (object.ReferenceEquals(managedObj, null))
                      return IntPtr.Zero;
                  if (!(managedObj is string))
                      throw new InvalidOperationException();

                  byte[] utf8bytes = Encoding.UTF8.GetBytes(managedObj as string);
                  IntPtr ptr = Marshal.AllocHGlobal(utf8bytes.Length + 1);
                  Marshal.Copy(utf8bytes, 0, ptr, utf8bytes.Length);
                  Marshal.WriteByte(ptr, utf8bytes.Length, 0);
                  return ptr;
              }

              public object MarshalNativeToManaged(IntPtr pNativeData)
              {
                  if (pNativeData == IntPtr.Zero)
                      return null;

                  List<byte> bytes = new List<byte>();
                  for (int offset = 0; ; offset++)
                  {
                      byte b = Marshal.ReadByte(pNativeData, offset);
                      if (b == 0)
                          break;
                      else
                          bytes.Add(b);
                  }
                  return Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count);
              }

              private static UTF8Marshaler instance = new UTF8Marshaler();
              public static ICustomMarshaler GetInstance(string cookie)
              {
                  return instance;
              }
          }

      7. 結合網上總結C++與NET中數據類型的對應

        // c++:HANDLE(void *) ---- c#:System.IntPtr  
        // c++:Byte(unsigned char) ---- c#:System.Byte  
        // c++:SHORT(short) ---- c#:System.Int16  
        // c++:WORD(unsigned short) ---- c#:System.UInt16  
        // c++:INT(int) ---- c#:System.Int16
        // c++:INT(int) ---- c#:System.Int32  
        // c++:UINT(unsigned int) ---- c#:System.UInt16
        // c++:UINT(unsigned int) ---- c#:System.UInt32
        // c++:LONG(long) ---- c#:System.Int32  
        // c++:ULONG(unsigned long) ---- c#:System.UInt32  
        // c++:DWORD(unsigned long) ---- c#:System.UInt32  
        // c++:DECIMAL ---- c#:System.Decimal  
        // c++:BOOL(long) ---- c#:System.Boolean  
        // c++:CHAR(char) ---- c#:System.Char  
        // c++:LPSTR(char *) ---- c#:System.String  
        // c++:LPWSTR(wchar_t *) ---- c#:System.String  
        // c++:LPCSTR(const char *) ---- c#:System.String  
        // c++:LPCWSTR(const wchar_t *) ---- c#:System.String  
        // c++:PCAHR(char *) ---- c#:System.String  
        // c++:BSTR ---- c#:System.String  
        // c++:FLOAT(float) ---- c#:System.Single  
        // c++:DOUBLE(double) ---- c#:System.Double  
        // c++:VARIANT ---- c#:System.Object  
        // c++:PBYTE(byte *) ---- c#:System.Byte[]  

        // c++:BSTR ---- c#:StringBuilder
        // c++:LPCTSTR ---- c#:StringBuilder
        // c++:LPCTSTR ---- c#:string
        // c++:LPTSTR ---- c#:[MarshalAs(UnmanagedType.LPTStr)] string  
        // c++:LPTSTR 輸出變量名 ---- c#:StringBuilder 輸出變量名
        // c++:LPCWSTR ---- c#:IntPtr
        // c++:BOOL ---- c#:bool   
        // c++:HMODULE ---- c#:IntPtr   
        // c++:HINSTANCE ---- c#:IntPtr  
        // c++:結構體 ---- c#:public struct 結構體{};  
        // c++:結構體 **變量名 ---- c#:out 變量名 //C#中提前申明一個結構體實例化后的變量名
        // c++:結構體 &變量名 ---- c#:ref 結構體 變量名

        // c++:WORD ---- c#:ushort
        // c++:DWORD ---- c#:uint
        // c++:DWORD ---- c#:int

        // c++:UCHAR ---- c#:int
        // c++:UCHAR ---- c#:byte
        // c++:UCHAR* ---- c#:string
        // c++:UCHAR* ---- c#:IntPtr

        // c++:GUID ---- c#:Guid
        // c++:Handle ---- c#:IntPtr
        // c++:HWND ---- c#:IntPtr
        // c++:DWORD ---- c#:int
        // c++:COLORREF ---- c#:uint
        // c++:unsigned char ---- c#:byte
        // c++:unsigned char * ---- c#:ref byte
        // c++:unsigned char * ---- c#:[MarshalAs(UnmanagedType.LPArray)] byte[]
        // c++:unsigned char * ---- c#:[MarshalAs(UnmanagedType.LPArray)] Intptr

        // c++:handle ---- c#:IntPtr
        // c++:hwnd ---- c#:IntPtr

        // c++:unsigned char & ---- c#:ref byte
        // c++:unsigned char 變量名 ---- c#:byte 變量名
        // c++:unsigned short 變量名 ---- c#:ushort 變量名
        // c++:unsigned int 變量名 ---- c#:uint 變量名
        // c++:unsigned long 變量名 ---- c#:ulong 變量名

        // c++:char 變量名 ---- c#:byte 變量名 // C++中一個字符用一個字節表示,C#中一個字符用兩個字節表示
        // c++:char 數組名[數組大小] ---- c#:MarshalAs(UnmanagedType.ByValTStr, SizeConst = 數組大小)] public string 數組名; ushort

        // c++:char * ---- c#:string // 傳入參數
        // c++:char * ---- c#:StringBuilder // 傳出參數
        // c++:char *變量名 ---- c#:ref string 變量名
        // c++:char *輸入變量名 ---- c#:string 輸入變量名
        // c++:char *輸出變量名 ---- c#:[MarshalAs(UnmanagedType.LPStr)] StringBuilder 輸出變量名

        // c++:char ** ---- c#:string
        // c++:char **變量名 ---- c#:ref string 變量名
        // c++:const char * ---- c#:string
        // c++:char[] ---- c#:string
        // c++:char 變量名[數組大小] ---- c#:[MarshalAs(UnmanagedType.ByValTStr,SizeConst=數組大小)] public string 變量名;  

        // c++:struct 結構體名 *變量名 ---- c#:ref 結構體名 變量名
        // c++:委托 變量名 ---- c#:委托 變量名

        // c++:int ---- c#:int
        // c++:int ---- c#:ref int
        // c++:int & ---- c#:ref int
        // c++:int * ---- c#:ref int  // C#中調用前需定義int 變量名 = 0;

        // c++:*int ---- c#:IntPtr
        // c++:int32 PIPTR * ---- c#:int32[]
        // c++:float PIPTR * ---- c#:float[]
         
        // c++:double** 數組名 ---- c#:ref double 數組名
        // c++:double*[] 數組名 ---- c#:ref double 數組名
        // c++:long ---- c#:int
        // c++:ulong ---- c#:int
          
        // c++:UINT8 * ---- c#:ref byte // C#中調用前需定義byte 變量名 = new byte(); 
             
        // c++:void * ---- c#:IntPtr   
        // c++:void * user_obj_param ---- c#:IntPtr user_obj_param
        // c++:void * 對象名稱 ---- c#:([MarshalAs(UnmanagedType.AsAny)]Object 對象名稱

        // c++:char, INT8, SBYTE, CHAR ---- c#:System.SByte   
        // c++:short, short int, INT16, SHORT ---- c#:System.Int16   
        // c++:int, long, long int, INT32, LONG32, BOOL , INT ---- c#:System.Int32   
        // c++:__int64, INT64, LONGLONG ---- c#:System.Int64   
        // c++:unsigned char, UINT8, UCHAR , BYTE ---- c#:System.Byte   
        // c++:unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR , __wchar_t ---- c#:System.UInt16   
        // c++:unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT ---- c#:System.UInt32   
        // c++:unsigned __int64, UINT64, DWORDLONG, ULONGLONG ---- c#:System.UInt64   
        // c++:float, FLOAT ---- c#:System.Single   
        // c++:double, long double, DOUBLE ---- c#:System.Double   

        // Win32 Types ---- CLR Type   
         
        // Struct需要在C#里重新定義一個Struct
        // CallBack回調函數需要封裝在一個委托里,delegate static extern int FunCallBack(string str);

        // unsigned char** ppImage替換成IntPtr ppImage
        // int& nWidth替換成ref int nWidth
        // int*, int&, 則都可用 ref int 對應
        // 雙針指類型參數,可以用 ref IntPtr
        // 函數指針使用c++: typedef double (*fun_type1)(double); 對應 c#:public delegate double fun_type1(double);
        // char* 的操作c++: char*; 對應 c#:StringBuilder;
        // c#中使用指針:在需要使用指針的地方 加 unsafe
        // unsigned char對應public byte
        /*
        * typedef void (*CALLBACKFUN1W)(wchar_t*, void* pArg); // 寬字符集
        * typedef void (*CALLBACKFUN1A)(char*, void* pArg);
        * bool BIOPRINT_SENSOR_API dllFun1(CALLBACKFUN1 pCallbackFun1, void* pArg);
        * 調用方式為
        * [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        * public delegate void CallbackFunc1([MarshalAs(UnmanagedType.LPWStr)] StringBuilder strName, IntPtr pArg); // 函數名有的可以不同
        * 
        */


       

      方法二:C++/CLR方式

       

      posted on 2021-02-06 13:25  碼杰  閱讀(1075)  評論(0)    收藏  舉報



      主站蜘蛛池模板: 草草浮力影院| 国产白丝jk捆绑束缚调教视频| 亚洲偷自拍国综合| 男人天堂亚洲天堂女人天堂| 成人性生交大片免费看中文| bt天堂新版中文在线| 国产亚洲精品aaaa片app| 久久一日本道色综合久久| 国产一区二区丰满熟女人妻| 亚洲最大成人网色| 永久免费在线观看蜜桃视频| 国产视频深夜在线观看| 国产亚洲精品久久久久秋霞 | 无码国产偷倩在线播放老年人| 久久精品国产亚洲不av麻豆| 一面膜上边一面膜下边视频| 中文激情一区二区三区四区| 日韩成人一区二区三区在线观看| 中文字幕无码视频手机免费看 | 亚洲成人av一区二区| 亚洲av成人无码精品电影在线| 四虎在线成人免费观看| 国产乱子伦视频在线播放| 她也色tayese在线视频| 四虎成人精品无码| 亚洲国产一区二区av| а天堂中文最新一区二区三区| 久热这里只有精品在线观看| 亚洲一区二区三区在线观看精品中文| 久久月本道色综合久久| 国产亚洲精品AA片在线播放天| 久久狠狠高潮亚洲精品夜色| 无遮挡粉嫩小泬久久久久久久| 亚洲人成网站在线无码| 成人无码午夜在线观看| 亚洲人妻精品中文字幕| 一区二区三区在线色视频| 麻豆tv入口在线看| 亚洲一精品一区二区三区| 男人猛躁进女人免费播放| 日韩精品成人区中文字幕|