2013-05-08 7 views
5

Ich habe mich um den googleverse und Stapelüberlauf geschaut und habe mehrere ähnliche Fragen zu diesem Thema, aber keine der Antworten, die ich gefunden habe, haben für mich gearbeitet. Ich bin ein neues Mitglied, deshalb darf ich die Antworten in der Frage von jemand anderem nicht kommentieren, um nach einer Klärung zu fragen, so dass ich auf meine eigenen Antworten zurückgreifen musste.übergeben Sie ein Array von Zeichenfolgen von C# zu einer C++ DLL und wieder zurück

Ok, also versuche ich, ein String-Array von einer C# -Anwendung an eine C++ - DLL übergeben und dann diese Informationen in einer anderen C# -Anwendung zu greifen. Ich glaube, dass ich richtig an C++ übergebe, aber ich kann keine richtigen Strings von der DLL zurückbekommen.

ich zu C wie ich vorbei ++ so:

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


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

Meine C++ Code sieht wie folgt aus:

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

Mein Code für die Informationen dann in meinen anderen C# Anwendung greifen wie folgt aussieht:

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

In der Theorie sollte dies basierend auf meiner Forschung funktionieren, wie ich mehrere andere Leute gesehen habe fast th Derselbe Code. In der Praxis geschieht, was ich passiere in:

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

und was aus der anderen Seite kommt zurück ist:

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

Falls einige es nicht aus irgendeinem Grunde sehen können oder einen anderen string [1 ] ist gleich H, -, eine dicke Linie, l und ein glückliches Gesichtssymbol. Das ist natürlich nicht das, was ich hineinlege.

Hat jemand eine Idee, wo ich damit falsch liegen könnte? Ich habe schon lange mit dem Kopf gegen dieses Problem geschlagen und könnte wirklich Hilfe gebrauchen, da es sich anfühlt, als würde ich hier etwas wirklich Einfaches vermissen.

Edit: per antijon Vorschlag habe ich meine SetGrammarData ändern, um eine Kopie der Saiten zu machen, aber ich laufe noch in ein Problem.

neuer Code:

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

Jetzt beende ich mit diesem Ausgang bis:

stringArray[0] = 8 
stringArray[1] = 

Das C# -Code ist gleich geblieben. Gibt es noch etwas, das ich ändern muss, das ich vermisse?

Edit2: gerade realisiert, dass Wchar_t wie ein Zeichen ist, kein String, nicht sicher, warum ich es wie eine Saite verhielt sich dachte. Zurück zum Zeichenbrett, müssen Sie herausfinden, wie Sie am besten ein wchar_t ** kopieren. Nicht so sehr mit C++, aber ich glaube nicht, dass es möglich ist, die Länge eines wchar_t * zu erhalten, ohne es in mir selbst weiterzugeben, aber ich werde es genauer betrachten müssen.

Edit3: Endlich hat es richtig funktioniert.

Hier ist, was ich am Ende mit:

(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: dachte ich, es richtig funktioniert hatte, falsch war. Ich testete mit einer exe, die zu sich selbst zurückging, aber als ich durch die dll zu einer anderen exe ging, würde nichts durchkommen. Ich habe jetzt daran zu arbeiten:

(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

Haben Sie versucht, das Array als Ref-Parameter zu übergeben? –

+0

siehe dies: http://StackOverflow.com/Questions/2372061/c-sharp-struct-No-Parameterless-Constructor-See-what-i-Need-to-Acomplish und http://StackOverflow.com/Questions/ 2345945/versucht-zu-lesen-oder-schreibgeschützt-speicher-das-ist-oft-ein-hinweis-dass-o und http://stackoverflow.com/questions/2344929/pointers-in-c-sharp- to-retrieve-reference-from-dllimport-Funktion –

+0

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

Antwort

3

Paar möglicher Probleme hier:

  1. standardmäßig .NET als wchar_t Marschall wird, nicht char. Sie müssen Ihre Eingabe-/Ausgabezeichenfolgenparameter mit MarshalAsAttribute zur Verwendung von char markieren.
  2. Wenn Sie die Zeichenfolgen beibehalten möchten, müssen Sie Kopien von ihnen innerhalb der C-Funktion erstellen. Die Zeiger, die Ihnen im Funktionsaufruf SetGrammarData zugewiesen wurden, sind nicht garantiert.
+0

Hmm, ich hatte nicht einmal # 2 in Betracht gezogen. Ich denke, es zeigt, dass ich zu lange an diesem Problem gearbeitet habe und zu viele Wiederholungen hatte, um so etwas vergessen zu haben. Ich werde versuchen, das zu korrigieren, da Sie wahrscheinlich richtig sind, da dies mein Hauptproblem ist. Ich werde es heute vielleicht nicht testen lassen, da ich sehr bald gehen muss. Möglicherweise müssen wir warten, bis morgen diese Antwort akzeptiert wird. – Adam

+0

hmm, ich habe versucht: EXPORT_API void SetGrammarData (wchar_t * strArr, int size) { löschen [] grammarData; grammarData = new wchar_t [Größe]; std :: memcpy (grammatikdaten, strArr, sizeof (wchar_t) * size); grammarDataLength = Größe; } EXPORT_API wchar_t * GetGrammarData() { Rückgabegrammatikdaten; } aber jetzt alles, was ich wieder heißt: string [0] = 8 string [1] = Gibt es etwas, was ich falsch mache, dass Sie sich bewusst sind? – Adam

Verwandte Themen