2013-05-08 809 views
5

我查看了googleverse和堆棧溢出,並且看到了幾個類似的問題,但沒有找到我找到的答案。我是一名新成員,因此我不允許在別人的問題中對答案發表評論以要求澄清,所以我不得不求助於自己的問題。將字符串數組從C#傳遞到C++ dll,然後再返回

好吧,所以我想從C#應用程序傳遞一個字符串數組到C++ DLL,然後在另一個C#應用程序中獲取這些信息。我相信我正確傳遞給C++,但是我無法從dll中獲得正確的字符串。

我傳遞到C++,像這樣:

[DllImport("KinectPlugins.dll", CallingConvention = CallingConvention.Cdecl)] 
    private static extern void SetGrammarData(string[] strArr, int size); 


    public void SetGrammar(string[] strArr) 
    { 
     SetGrammarData(strArr, strArr.Length); 
    } 

我的C++代碼如下所示:

#define EXPORT_API __declspec(dllexport) 
#pragma data_seg(".SHARED") 
    char** grammarData; 
    int grammarDataLength = 0; 
#pragma data_seg() 
#pragma comment(linker, "/section:.SHARED,RWS") 

EXPORT_API void SetGrammarData(char** strArr, int size) 
{ 
    grammarData = strArr; 
    grammarDataLength = size; 
} 

EXPORT_API int GetGrammarDataLength() 
{ 
    return grammarDataLength; 
} 
EXPORT_API char** GetGrammarData() 
{ 
    return grammarData; 
} 

我因爲當時我在其他C#應用程序抓取信息的代碼如下所示:

[DllImport("KinectPlugins.dll")] 
private static extern IntPtr GetGrammarData(); 
[DllImport("KinectPlugins.dll")] 
private static extern int GetGrammarDataLength(); 

public string[] GetGrammar() 
{ 
    int size = GetGrammarDataLength(); 
    List<string> list = new List<string>(); 
    IntPtr ptr = GetGrammarData(); 
    IntPtr strPtr; 
    for (int i = 0; i < size; i++) 
    { 
     Console.WriteLine("i = " + i); 
     strPtr = Marshal.ReadIntPtr(ptr); 
     list.Add(Marshal.PtrToStringAnsi(strPtr)); 
     ptr += Marshal.SizeOf(typeof(IntPtr)); 
    } 
    return list.ToArray(); 
} 

理論上這應該基於我的研究工作,因爲我已經看到其他幾個人幾乎使用e相同的代碼。在實踐中,發生的事情是我通過:

SetGrammar(new string[] { "b", "a" }); 

什麼回來了對方:

stringArray[0] = 
stringArray[1] = H-▬l☺ 

在某些情況下不能查看它出於某種原因或其他字符串數組[1 ]等於H, - ,一條粗線,l和一張滿臉幸福的符號。這顯然不是我投入的。

有沒有人有一個想法,我可能會出錯呢?我一直在對付這個問題,並且可以真正使用一些幫助,因爲這感覺就像我在這裏錯過了一些非常簡單的事情。

編輯:每antijon的建議 因爲我沒有改變我的SetGrammarData使字符串的副本,但我仍然在運行到一個問題。

新代碼:

(inside the data_seg) 
wchar_t* grammarData; 
(end data_seg) 

EXPORT_API void SetGrammarData(wchar_t* strArr, int size) 
{ 
    delete[] grammarData; 
    grammarData = new wchar_t[size]; 
    std::memcpy(grammarData, strArr, sizeof(wchar_t) * size); 
    grammarDataLength = size; 
} 
EXPORT_API wchar_t* GetGrammarData() 
{ 
    return grammarData; 
} 

現在我結束了這樣的輸出:

stringArray[0] = 8 
stringArray[1] = 

的C#代碼保持不變。還有什麼我需要改變,我失蹤了?

EDIT2: 剛剛意識到wchar_t的就像是一個字符,而不是一個字符串,不知道爲什麼,我覺得它的表現就像一個字符串。回到繪圖板,需要弄清楚如何最好地複製wchar_t **。這不是C++的經驗,但我不認爲有可能獲得wchar_t *的長度而不傳遞給自己,但我必須研究它。

編輯3: 終於得到它正常工作。

這裏是我結束了:

(inside the data_seg) 
std::wstring* grammarData; 
(end data_seg) 

EXPORT_API void SetGrammarData(wchar_t** strArr, int size) 
{ 
    delete[] grammarData; 
    grammarDataLength = size; 
    grammarData = new std::wstring[size]; 
    for(int i = 0; i < size; i++) 
    { 
     grammarData[i] = std::wstring(strArr[i]); 
    } 
} 

EXPORT_API const wchar_t** GetGrammarData() 
{ 
    const wchar_t** wct = new const wchar_t*[grammarDataLength]; 
    for(int i = 0;i<grammarDataLength;i++) 
    { 
     const wchar_t* t = grammarData[i].c_str(); 
     wct[i] = t; 
    } 
    return wct; 
} 

Edit4: 以爲我擁有正常工作,是不正確的。我正在測試一個exe文件,但是在通過dll傳遞給另一個exe文件時,沒有任何東西會通過。我現在有工作:

(inside the data_seg) 
wchar_t grammarData[32][50] = {}; 
(end data_seg) 

EXPORT_API void SetGrammarData(wchar_t** strArr, int size) 
{ 
    grammarDataLength = size; 
    for(int i = 0; i < size; i++) 
    { 
     wcscpy(grammarData[i], strArr[i]); 
    } 
    grammarDataChanged = 1; 
} 

EXPORT_API wchar_t** GetGrammarData() 
{ 
    wchar_t** wct = new wchar_t*[grammarDataLength]; 
    for(int i = 0;i<grammarDataLength;i++) 
    { 
     wct[i] = grammarData[i]; 
    } 

    grammarDataChanged = 0; 
    return wct; 
} 
+0

,您是否試圖傳遞數組作爲'ref'參數? – 2013-05-08 18:19:25

+0

看到這一點:http://stackoverflow.com/questions/2372061/c-sharp-struct-no-parameterless-constructor-see-what-i-need-to-accomplish和http://stackoverflow.com/questions/ 2345945 /試圖讀取或寫入保護存儲器,這是經常是一個指示,即o和http://stackoverflow.com/questions/2344929/pointers-in-c-sharp-到檢索參考 - 從 - dllimport的功能 – 2013-05-08 18:21:39

+0

和http://stackoverflow.com/questions/2343272/dllimport-unmanaged-non-net-dll-to-net-project-representing-char-and-void – 2013-05-08 18:22:05

回答

3

夫婦在這裏可能出現的問題:

  1. 默認情況下,.NET將作爲元帥wchar_t,不char。你將需要用MarshalAsAttribute來標記你的輸入/輸出字符串參數來使用char。
  2. 如果你想保留字符串,你需要在C函數中複製它們。在函數調用SetGrammarData中給予您的指針不保證持續存在。
+0

嗯,我甚至沒有考慮#2。我想這表明我一直在研究這個問題太久,並且有太多的迭代已經忘記了這樣的事情。我會試着解決這個問題,因爲你可能正確的解決了這個問題。我今天可能沒有測試過,因爲我必須很快離開。可能需要等待明天接受這個答案。 – Adam 2013-05-08 19:17:43

+0

嗯,我試過了: EXPORT_API void SetGrammarData(wchar_t * strArr,int size) { delete [] grammarData; grammarData = new wchar_t [size]; std :: memcpy(grammarData,strArr,sizeof(wchar_t)* size); grammarDataLength = size; } EXPORT_API wchar_t * GetGrammarData() { return grammarData; } 但現在,我得到的回覆是: 字符串數組[0] = 8 字符串數組[1] = 有沒有別的東西,我做錯了什麼,你知道嗎? – Adam 2013-05-09 13:08:48

相關問題