程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程綜合問答 >> .net-C#調用c++的dll執行帶字符串參數的函數時遇到的問題

.net-C#調用c++的dll執行帶字符串參數的函數時遇到的問題

編輯:編程綜合問答
C#調用c++的dll執行帶字符串參數的函數時遇到的問題

我在c++項目中實現函數:
extern "C" __declspec(dllexport) int FUNC1(const char* xmlSta, char* fileOut)
{
return 0;
}
然後編譯成動態庫a.dll,並在C#項目中引用,
用靜態加載的方式,是可以運行的,代碼如下(只寫調用的部分):
[DllImport("a.dll", EntryPoint = "FUNC1", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int FUNC1(string xmlSta, StringBuilder fileOut);

        StringBuilder sbr = new StringBuilder(10);
        int r1 = FUNC1("abc ", sbr);        //可以運行!

但是用動態加載的方式,卻報錯,代碼如下:

public static class NativeMethod
{
    [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
    public static extern int LoadLibrary(
        [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);

    [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
    public static extern IntPtr GetProcAddress(int hModule,
        [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

    [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
    public static extern bool FreeLibrary(int hModule);
}

/// <summary>
/// 函數指針
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
delegate int FUNC1(string xmlSta, StringBuilder fileOut);   

class Program
{
    static void Main(string[] args)
    {
        StringBuilder sbr = new StringBuilder(10);
        //1. 動態加載C++ Dll
        int hModule = NativeMethod.LoadLibrary(@"a.dll");
        if (hModule == 0) return;
        //2. 讀取函數指針
        IntPtr intPtr = NativeMethod.GetProcAddress(hModule, "FUNC1");
        //3. 將函數指針封裝成委托
        FUNC1 cFUNC1 = (FUNC1)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(FUNC1));
        //4. 測試
        Console.WriteLine(cFUNC1("abc ", sbr));

        Console.Read();
    }
}

報錯信息是:托管調試助手“PInvokeStackImbalance”在“E:\WCF\CPP\bin\test.vshost.exe”中檢測到問題。

其他信息: 對 PInvoke 函數“test!test.FUNC1::Invoke”的調用導致堆棧不對稱。原因可能是托管的 PInvoke 簽名與非托管的目標簽名不匹配。請檢查 PInvoke 簽名的調用約定和參數與非托管的目標簽名是否匹配。

兩種方式不都一樣嗎?為什麼第二種方式會報錯?因為第一種方式有時運行很慢,要等很久,所以我想用第二種方式在程序啟動時先LoadLibrary,之後就不會出現很慢的情況,但是第二種方式總是出錯,只有在參數沒有字符串類型的情況下才能運行,但是確實需要傳字符串參數,哪位高手能夠給個指點,代碼該如何修改呢?

最佳回答:


C#默認是stdcall調用約定,你可以把委托改成下面寫法
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
delegate int FUNC1(string xmlSta, StringBuilder fileOut);

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