回覆列表
  • 1 # 儘快愛你

    第一步,我先從簡單的調用出發,定義了一個簡單的函式,該函式僅僅實現一個整數加法求和: LIBEXPORT_API int mySum(int a,int b){ return a+b;} C# 匯入定義: public class RefComm { [DllImport("LibEncrypt.dll", EntryPoint=" mySum ", CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] public static extern int mySum (int a,int b); } 在C#中呼叫測試: int iSum = RefComm.mySum(,); 執行檢視結果iSum為5,呼叫正確。第一步試驗完成,說明在C#中能夠呼叫自定義的動態連結庫函式。 第二步,我定義了字串操作的函式(簡單起見,還是採用前面的函式名),返回結果為字串: LIBEXPORT_API char *mySum(char *a,char *b){sprintf(b,"%s",a); return a;} C# 匯入定義: public class RefComm { [DllImport("LibEncrypt.dll", EntryPoint=" mySum ", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)] public static extern string mySum (string a, string b); } 在C#中呼叫測試: string strDest=""; string strTmp= RefComm.mySum("45", strDest); 執行檢視結果 strTmp 為"45",但是strDest為空。我修改動態連結庫實現,返回結果為串b: LIBEXPORT_API char *mySum(char *a,char *b){sprintf(b,"%s",a) return b;} 修改 C# 匯入定義,將串b修改為ref方式: public class RefComm { [DllImport("LibEncrypt.dll", EntryPoint=" mySum ", CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] public static extern string mySum (string a, ref string b); } 在C#中再呼叫測試: string strDest=""; string strTmp= RefComm.mySum("45", ref strDest); 執行檢視結果 strTmp 和 strDest 均不對,含不可見字元。再修改 C# 匯入定義,將CharSet從Auto修改為Ansi: public class RefComm { [DllImport("LibEncrypt.dll", EntryPoint=" mySum ", CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] public static extern string mySum (string a, string b); } 在C#中再呼叫測試: string strDest=""; string strTmp= RefComm. mySum("45", ref strDest); 執行檢視結果 strTmp 為"45",但是串 strDest 沒有賦值。第二步實現函式返回串,但是在函數出口引數中沒能進行輸出。再次修改 C# 匯入定義,將串b修改為引用(ref): public class RefComm { [DllImport("LibEncrypt.dll", EntryPoint=" mySum ", CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] public static extern string mySum (string a, ref string b); } 執行時呼叫失敗,不能繼續執行。 第三步,修改動態連結庫實現,將b修改為雙重指標: LIBEXPORT_API char *mySum(char *a,char **b){sprintf((*b),"%s",a); return *b;} C#匯入定義: public class RefComm { [DllImport("LibEncrypt.dll", EntryPoint=" mySum ", CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] public static extern string mySum (string a, ref string b); } 在C#中呼叫測試: string strDest=""; string strTmp= RefComm. mySum("45", ref strDest); 執行檢視結果 strTmp 和 strDest 均為"45",呼叫正確。第三步實現了函數出口引數正確輸出結果。 第四步,修改動態連結庫實現,實現整數引數的輸出: LIBEXPORT_API int mySum(int a,int b,int *c){ *c=a+b; return *c;} C#匯入的定義: public class RefComm { [DllImport("LibEncrypt.dll", EntryPoint=" mySum ", CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] public static extern int mySum (int a, int b,ref int c); } 在C#中呼叫測試: int c=0; int iSum= RefComm. mySum(,, ref c); 執行檢視結果iSum 和c均為5,呼叫正確。 經過以上幾個步驟的試驗,基本掌握瞭如何定義動態庫函式以及如何在 C# 定義匯入,有此基礎,很快我實現了變長加密函式在 C# 中的呼叫,至此目標實現。 三、結論 在 C# 中呼叫 C++ 編寫的動態連結庫函式,如果需要出口引數輸出,則需要使用指標,對於字串,則需要使用雙重指標,對於 C# 的匯入定義,則需要使用引用(ref)定義。 對於函式返回值,C# 匯入定義和 C++ 動態庫函式宣告定義需要保持一致,否則會出現函式呼叫失敗。定義匯入時,一定注意 CharSet 和 CallingConvention 引數,否則導致呼叫失敗或結果異常。執行時,動態連結庫放在 C# 程式的目錄下即可,我這裡是一個 C# 的動態連結庫,兩個動態連結庫就在同一個目錄下執行。

  • 中秋節和大豐收的關聯?
  • 當途歌們紛紛倒下,做分時租賃的GoFun是如何實現盈利的?