2010-06-10 21 views
1

以下.NET原生C代碼不工作,任何想法爲什麼這個顯式P/Invoke不起作用?

extern "C" { 
    TRADITIONALDLL_API int TestStrRef(__inout char* c) { 
    int rc = strlen(c); 
    std::cout << "the input to TestStrRef is: >>" << c << "<<" ; 
    c = "This is from the C code "; 
    return rc; 
    } 
} 

[DllImport("MyDll.dll", SetLastError = true)] 
static extern int TestStrRef([MarshalAs(UnmanagedType.LPStr)] ref string s); 
String abc = "InOut string"; 
TestStrRef(ref abc); 

此時Console.WriteLine(ABC)應打印「這是從C代碼」,但並沒有任何想法上怎麼了 ?

僅供參考 - 我沒有使用ref類型的字符串另一個測試功能,它工作得很好

+1

請在C工作的第一位。 – 2010-06-10 15:23:35

+0

本機C - 它確實 C .net - 不知道:( – Kumar 2010-06-11 13:25:40

回答

5

你的代碼錯在C面也。 __inout註釋只是告訴編譯器,你可以改變「c」參數指向的緩衝區。但是指針本身位於堆棧中,如果修改了「c」參數,它不會返回給調用者。 您的聲明可能看起來像:

extern "C" { 
    TRADITIONALDLL_API int TestStrRef(__inout char** c) { 
    int rc = strlen(*c); 
    std::cout << "the input to TestStrRef is: >>" << *c << "<<" ; 
    *c = "This is from the C code "; 
    return rc; 
    } 
} 

和C#的一面:

[DllImport("MyDll.dll", SetLastError = true)] 
static extern int TestStrRef(ref IntPtr c); 

{ 
    String abc = "InOut string"; 
    IntPtr ptrOrig = Marshal.StringToHGlobalAnsi(abc)   
    IntPtr ptr = ptrOrig; // Because IntPtr is structure, ptr contains copy of ptrOrig 
    int len = TestStrRef(ref ptr); 
    Marshal.FreeHGlobal(ptrOrig); // You need to free memory located to abc' native copy 
    string newAbc = Marshal.PtrToStringAnsi(ptr); 
    // You cannot free memory pointed by ptr, because it pointed to literal string located in dll code. 
} 
0

這是否對你的工作?基本上只需添加CallingConvention = CallingConvention.Cdecl到DllImport語句。您可能還需要指定CharSet(例如:字符集:= CharSet.Unicode)

[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)] 
static extern int TestStrRef([MarshalAs(UnmanagedType.LPStr)] ref string s); 
+0

爲什麼會有調用慣例重要?調用方法已經爲OP工作。 – 2010-06-10 14:36:34

+0

反正我試過了,它不起作用! – Kumar 2010-06-10 14:45:10