c++ dllVariant in VB.Net

  • VB.NET

Es gibt 93 Antworten in diesem Thema. Der letzte Beitrag () ist von borhan.

    Hallo,

    1.
    - ich habe eine Datenbankabfrage, die ich in einem VARIANT speichere. Es muss nicht unbedingt VARIANT sein es kann auch gerne ein Char Array sein.
    - die möglichen Inhalte sind alle char*
    - es ist ein extern "C" Funktion.
    - ein datei.h habe ich nicht angelegt aber ein lib und dll datei habe ich.
    2.
    ich benutze
    -Visual 2010 Express

    3.

    Ich möchte, von der Dll ein 2d. Array (von Strings) bekommen (kann auch VARIANT sein), die ich dann in VB verarbeiten möchte.
    Danke für den Link guck ich mir gleich an.

    borhan schrieb:

    Ich möchte, von der Dll ein 2d. Array (von Strings) bekommen [...], die ich dann in VB verarbeiten möchte.
    Aha - das ist doch mal ne Ansage.

    Du kannst 2D-Arrays (unbekannter Größe) nicht direkt marshallen, weil der Marshaller die Länge der Zeilen nicht kennt.

    In C++ musst du das Array in einer Struktur zusammen mit Größenangaben zurückgeben. Außerdem muss angeforderter Speicher freigegeben werden. Also brauchst du zwei Funktionen mit diesen Signaturen:

    Quellcode

    1. extern "C" {
    2. typedef struct retval {
    3. char** arrayRef; // z.B. = (char**) new const char*[2][2];
    4. int count; // 2
    5. int lLen; // 2
    6. } RETVAL;
    7. // Gibt ein 2D-Array in der Struktur zurück
    8. __declspec(dllexport) RETVAL* __stdcall get2darray();
    9. // Gibt die Struktur frei
    10. __declspec(dllexport) void __stdcall free2darray();
    11. }


    In VB brauchst du einen "Custom Marshaller", um die Rückgabe zu verarbeiten. Hier die Vorgehensweise:
    - Implementiere die Schnittstelle ICustomMarshaler
    - In der Methode MarshalNativeToManaged() musst du die Struktur auslesen:
    -- arrayRef auslesen (Marshal.ReadIntPtr)
    -- Zeilenzahl und -Länge auslesen (Marshal.ReadInt32)
    -- Speicher von arrayRef der Größe count * lLen lesen (mit Marshal.Copy(), ergibt IntPtr-Array)
    -- String(count)(lLen) auf dem verwalteten Heap anlegen
    -- Jeden Zeiger des Zeigerarrays mit Marshal.PtrToStringAnsi() in das neue 2D-Array einlesen
    -- String()() zurückgeben

    - In der Methode CleanUpNativeData() solltest du free2darray() aufrufen, um den Speicher der RETVAL-Struktur freizugeben

    - Den Rest musst du erstmal nicht implementieren.
    Gruß
    hal2000

    borhan schrieb:

    Ich möchte, von der Dll ein 2d. Array (von Strings) bekommen (kann auch VARIANT sein), die ich dann in VB verarbeiten möchte.
    Dann mach Dir keine native C++-DLL, sondern mach Dir eine CLI-DLL.
    Hatten wir bereits.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo und danke,

    ich bin dabei den Ansatz zu realisieren. Allerdings bekomme ich den Array nicht gefüllt.

    VB.NET-Quellcode

    1. extern "C" {
    2. typedef struct retval {
    3. char** arrayRef;// = (char**) new const char*[2][2];
    4. int count; // 2
    5. int lLen; // 2
    6. }RETVAL;
    7. // Gibt ein 2D-Array in der Struktur zurück
    8. __declspec(dllexport) RETVAL* __stdcall get2darray()
    9. {
    10. retval test;
    11. test.arrayRef = (char**) new const char*[1][1];
    12. test.arrayRef[0][0] = "das";
    13. test.count=1;
    14. test.lLen = 1;
    15. return &test;
    16. }

    test.arrayRef[0][0] = "das"; Damit funktioniert es nicht ! die Fehlermeldung besagt: Ein Typo von const char* kann keiner Entität vom Typ char zugewiesen werden
    Wenn du ein String Array hast also 2 dim. Char/wchar_t Array und auf [0][0] zugreifst greifst du auf den ersten Char im ersten String zu. Das ist ein Char und kein Char*. Darf ich Fragen wieso du es nicht so machst wie Rods dir vorgeschlagen hat ?
    Daten von C++ nach .NET sollten in CLI übergeben werden.
    Hatten wir schon.
    Lernresistent?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Du musst auch Speicher anfordern:

    Quellcode

    1. extern "C" {
    2. typedef struct retval {
    3. char** arrayRef;// = (char**) new const char*[2][2];
    4. int count; // 2
    5. int lLen; // 2
    6. } RETVAL;
    7. // Gibt ein 2D-Array in der Struktur zurück
    8. __declspec(dllexport) RETVAL* __stdcall get2darray()
    9. {
    10. RETVAL* test = new RETVAL(); // Speicher vom Heap benutzen! (nicht vom Stack)
    11. test->arrayRef = (char**) new const char*[1][1];
    12. test->count=1;
    13. test->lLen = 1;
    14. *(test->arrayRef) = new char*("das"); // nur erstes Element
    15. // andere Elemente:
    16. //char* tmp = new char*("dein String");
    17. //char** ref = test->arrayRef + ([Zeile] * test->lLen + [Spalte]);
    18. //*ref = tmp;
    19. return test;
    20. }
    21. }
    Gruß
    hal2000

    borhan schrieb:

    Ich weiss leider nur nicht wie ich das mit Cli machen soll.
    In Post #33 habe ich Dir ein CLI Beispielprojekt gepostet.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Da Du das CLI-Projekt ignorierst, gehe ich davon aus, dass Du keine Hilfe mehr brauchst.
    Fahr weiter mit dem Holzroller.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Dann frage ich mich, wieso Du dazu keine Frage gestellt hast, das nenn ich ignorieren. X(
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    borhan schrieb:

    wie überhaupt ein cli Projekt anlegen kann?
    Ich hab Dir ein komplettes Test-Projekt gepostet.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo,

    erstmal danke an alle, die so geduldig sind und mir immer noch helfen. Ich habe einige Fragen:
    Frage1: Die ClipTestLib.cpp ist leer! Was muss ich denn hier anderes machen als in einem normalen Dll.
    Frage2: Wie gehe ich den Vor lasse ich den Rückgabewert meiner Funktion bei Variant oder was muss ich den anders machen!
    zu 1.: Der Code ist in der CliTestLib.h
    zu 2.: Du musst was anders machen, z.B. ein String-Array zurückgeben (das ist .NET-Code!!!)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!