2012-09-10 50 views
3

我是C#和封送的新手。我需要在C#中使用我的C函數,但是我從C func返回的值不正確(或者我不知道如何將它轉換爲正確的答案)。DllImport和char Marshaling

c來源:

#include "main.h" 

char *Ololo(char *arg, int &n3) 
{ 
    char *szRet; 
    szRet=(char*)malloc(strlen(arg)+1); 
    strcpy(szRet,arg); 
    n3 = strlen(szRet); 
    return szRet; 
} 

C頭:

extern "C" __declspec(dllexport) char *Ololo(char *arg, int &n3); 

C#源: 「伯仲」

class Program 
{ 
    [DllImport(@"F:\Projects\service\dll\testDLL2.DLL", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] 
    public static extern IntPtr Ololo([In] char[] arg, ref Int32 n3); 

    static void Main(string[] args) 
    { 
     string n1 = "ololo"; 
     char[] chars = new char[n1.Length]; 
     chars = n1.ToCharArray(); 
     Int32 n3 = 0; 
     IntPtr result; 
     result = Ololo(chars, ref n3); 
     string n4 = Marshal.PtrToStringUni(result,n3); 
     Console.WriteLine(n4); 
    } 
} 

我已經得到了一些回報,像

對不起,我英文不好

----------------------解決--------------- --------

class Program 
    { 
     [DllImport(@"F:\Projects\service\dll\testDLL2.DLL", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] 
     public static extern IntPtr Ololo([MarshalAs(UnmanagedType.LPStr)]string arg, ref Int32 n3); 

     static void Main(string[] args) 
     { 
      string n1 = "ololo"; 
      Int32 n3 = 0; 
      int n2 = n1.Length; 
      IntPtr result; 
      result = Ololo(n1, ref n3); 
      string n4 = Marshal.PtrToStringAnsi(result, n3); 
      Console.WriteLine(n4); 
     } 
    } 

工作正常。在n3中,我得到了5和n4奧洛洛!感謝您的快速解答!

+0

btw'int&n3'不是C,它的C++表示法。 –

+0

你還沒有解決任何問題,代碼泄漏了字符串的內存。 –

+0

可能重複的[Char *編組在C#](http://stackoverflow.com/questions/1808581/char-marshalling-in-c-sharp) –

回答

3

public static extern IntPtr Ololo([In] char[] arg, ref Int32 n3);

IntPtr是錯誤的返回類型,本質上是要返回的字符串,而不是一個字符串指針。在C中,你可以使用指向你的字符串的指針,使用char*,.NET中的等價物將使用這個:[MarshalAs(UnmanagedType.LPStr)]string。這應該正確地將char*編號爲string

IntPtr代表一個指針類型,它讓你的實際字符串沒用。

您看起來應該將StringBuilder放入您的Marshalled函數中,而不是char[]。然後至少你應該得到正確的字符串到你的C函數。

+0

我認爲'IntPtr'是正確的,因爲'n3'返回我1和int'IntPtr'我得到了第一個字母(o)。但爲什麼我有'n3' = 1?我認爲它需要是5.因爲我認爲'[In] char [] arg'是不正確的。但是什麼是正確的? – Treno1

+0

查看我編輯的答案 –

+0

@ Treno1如果你返回'IntPtr',你在.NET中的函數將永遠不會給你整個字符串。 –

0

編組器不會終止char陣列。它會這樣做,因爲你告訴它 - 如果你告訴它。你很幸運,因爲.NET中的一個char是UTF-16,這是16位寬,第二個字節將爲零,因爲這是UTF-16中的'o',因此給出了strlen爲1。一個被管理的字符串作爲一個以空字符結尾的C字符串比你似乎欣賞的要高一點點。所以,讓編組完成所有工作 - 它已經知道如何完成這項工作。

public static extern [MarshalAs(UnmanagedType.LPStr)]string Ololo(
    [MarshalAs(UnmanagedType.LPStr)]string arg, 
    ref int n3 
); 
static void Main(string[] args) 
{ 
    string n1 = "ololo"; 
    Int32 n3 = 0; 
    string n4 = Ololo(chars, ref n3); 
    Console.WriteLine(n4); 
} 
+0

由於[MarshalAs(UnmanagedType.LPStr)]不能​​在類,結構或接口的聲明中,VS 2010認爲'public static extern [MarshalAs(UnmanagedType.LPStr)] string Ololo'不正確。 – Treno1

+0

不是。您必須未能複製DLLImport屬性,或將聲明放在錯誤的位置。 – Puppy

+0

謝謝!解決了!向上! – Treno1