2013-05-08 45 views
5

Tôi đã xem xung quanh googleverse và stack tràn và đã thấy một số câu hỏi tương tự nhưng điều này không có câu trả lời tôi đã tìm thấy đã làm việc cho tôi. Tôi là một thành viên mới vì vậy tôi không được phép bình luận về câu trả lời trong câu hỏi của người khác để yêu cầu làm rõ vì vậy tôi phải nghỉ mát để tự hỏi mình.truyền một chuỗi các chuỗi từ C# đến một dll C++ và ngược lại

Ok vì vậy tôi đang cố gắng chuyển một mảng chuỗi từ ứng dụng C# tới một tệp C++ và sau đó lấy thông tin đó trong ứng dụng C# khác. Tôi tin rằng tôi đang đi đến C + + đúng cách nhưng tôi không thể có được chuỗi thích hợp trở lại từ dll.

tôi đi qua C++ như sau:

[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 My ++ mã trông như thế này:

#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; 
} 

Mã của tôi cho sau đó lấy thông tin trong C# ứng dụng khác của tôi trông như thế này:

[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(); 
} 

Về lý thuyết, điều này nên dựa trên nghiên cứu của tôi vì tôi đã thấy một số người khác sử dụng gần như thứ cùng một mã. Trên thực tế, những gì xảy ra là tôi vượt qua trong:

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

và những gì trở lại ra phía bên kia là:

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

Trong trường hợp một số không thể xem nó vì một lý do này hay cách khác stringArray [1 ] bằng H, -, một đường dày, l và một biểu tượng khuôn mặt hạnh phúc. Điều này rõ ràng không phải là những gì tôi đưa vào.

Có ai có ý tưởng về việc tôi có thể làm sai điều này không? Tôi đã đập đầu của tôi chống lại vấn đề này trong một thời gian và thực sự có thể sử dụng một số trợ giúp vì nó cảm thấy như tôi đang thiếu một cái gì đó thực sự đơn giản ở đây.

Edit: theo gợi ý antijon của tôi đã thay đổi SetGrammarData của tôi để tạo ra một bản sao của chuỗi nhưng tôi vẫn đang chạy vào một vấn đề.

mã mới:

(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; 
} 

Bây giờ tôi kết thúc với kết quả này:

stringArray[0] = 8 
stringArray[1] = 

Mã C# vẫn giống nhau. Có cái gì khác tôi cần phải thay đổi mà tôi đang thiếu?

Chỉnh sửa2: Chỉ cần nhận ra rằng wchar_t giống như một char, không phải là một chuỗi, không chắc chắn lý do tại sao tôi nghĩ rằng nó hoạt động như một chuỗi. Quay lại bảng vẽ, cần tìm ra cách sao chép tốt nhất một wchar_t **. Không phải là kinh nghiệm với C + + nhưng tôi không nghĩ rằng nó có thể để có được chiều dài của một wchar_t * mà không đi qua nó trong bản thân mình, nhưng tôi sẽ phải nhìn vào nó.

Chỉnh sửa3: Cuối cùng nó hoạt động bình thường.

Đây là những gì tôi đã kết thúc với:

(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: tưởng tôi đã có nó làm việc đúng cách, không đúng. Tôi đã thử nghiệm với một exe đi lại cho chính nó, nhưng khi đi qua dll khác exe không có gì sẽ đi qua. bây giờ tôi có nó làm việc:

(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

bạn có thử chuyển mảng đó dưới dạng thông số 'ref' không? –

+0

thấy điều này: http://stackoverflow.com/questions/2372061/c-sharp-struct-no-parameterless-constructor-see-what-i-need-to-accomplish và http://stackoverflow.com/questions/ 2345945/cố gắng đọc hoặc ghi-bảo vệ-bộ nhớ-này-thường-một-chỉ-rằng-o và http://stackoverflow.com/questions/2344929/pointers-in-c-sharp- to-retrieve-reference-from-dllimport-function –

+0

và http://stackoverflow.com/questions/2343272/dllimport-unmanaged-non-net-dll-to-net-project-representing-char-and-void –

Trả lời

3

Couple của các vấn đề có thể ở đây:

  1. Theo mặc định, .NET sẽ sắp xếp như wchar_t, không char. Bạn sẽ cần phải đánh dấu các tham số chuỗi đầu vào/đầu ra của bạn với MarshalAsAttribute để sử dụng char.
  2. Nếu bạn muốn giữ các chuỗi, bạn sẽ cần tạo bản sao của chúng trong hàm C. Các con trỏ được cung cấp cho bạn trong lời gọi hàm tới SetGrammarData không được đảm bảo vẫn tồn tại.
+0

Hmm, tôi thậm chí không được coi là số 2. Tôi đoán nó đi để cho thấy tôi đã được làm việc về vấn đề này quá lâu và đã có quá nhiều lần lặp lại để quên một cái gì đó như thế. Tôi sẽ cố gắng sửa chữa như bạn có thể đúng với đó là vấn đề lớn của tôi. Tôi có thể không có nó thử nghiệm ngày hôm nay mặc dù như tôi phải rời khỏi rất sớm. Có thể cần phải chờ ngày mai để chấp nhận câu trả lời này. – Adam

+0

hmm, tôi đã thử: EXPORT_API void SetGrammarData (wchar_t * strArr, kích thước int) { xóa [] ngữ phápData; ngữ phápData = new wchar_t [size]; std :: memcpy (ngữ phápData, strArr, sizeof (wchar_t) * size); ngữ phápDataLength = size; } EXPORT_API wchar_t * GetGrammarData() { trả về ngữ phápData; } nhưng bây giờ tất cả tôi nhận được lại là: stringArray [0] = 8 stringArray [1] = Có cái gì khác tôi đang làm sai mà bạn nhận thức được? – Adam

Các vấn đề liên quan