vb.net array to c-Dll

  • VB.NET
  • .NET (FX) 4.0

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von exc-jdbi.

    vb.net array to c-Dll

    Guten Tag Community

    Ich hab vor ein paar Tage diesen Thread entdeckt die ich als Grundlage nutze. Und jetzt versuche ich schon eine Weile eine ganz normale Array an die C-Dll zu übergeben (und wieder zurück). Vielleicht kann mir jemand einen Tip geben, wie ich da vorgehen muss.

    Mir wäre eventuell auch schon mit einem sehr guten Tut zum Thema Marhelling geholfen, in dem einige gute Beispiele vorhanden sind. Vorzugsweise auf Deutsch.

    C-Quellcode

    1. //Test.dll
    2. extern "C"
    3. __declspec(dllexport) BOOL _stdcall Test2(char **cArrStr,char ***pArr,int iLenArr){
    4. BOOL ret=false;
    5. static std::vector<char*>vArr;
    6. vArr.push_back("Dll");
    7. *pArr=&vArr[0];
    8. if(*pArr[0]=="Dll")
    9. {ret=true;}
    10. return ret;
    11. }


    VB.NET-Quellcode

    1. Module Module1
    2. Sub Main()
    3. Dim p3, p4 As IntPtr
    4. Dim strBack As String = String.Empty
    5. Dim chArr(,) As Char = {}
    6. Dim strArrBack() As String = {}
    7. Dim strArr() As String = New String() {"Ich", "bin", "eine", "Array"}
    8. Try
    9. chArr = New Char(strArr.Length - 1, 256 - 1) {}
    10. For i As Integer = 0 To strArr.Length - 1
    11. For j As Integer = 0 To strArr(i).Length - 1
    12. chArr(i, j) = strArr(i)(j)
    13. Next
    14. Next
    15. 'p3 = Marshal.AllocHGlobal(Marshal.SizeOf(chArr.GetValue(chArr.GetLowerBound(0), chArr.GetLowerBound(1))))
    16. 'Marshal.StructureToPtr(chArr.GetValue(chArr.GetLowerBound(0), chArr.GetLowerBound(1)), p3, True)
    17. p4 = Marshal.AllocHGlobal(Marshal.SizeOf(IntPtr.Zero))
    18. If (dll.Test2(p3, p4, chArr.GetUpperBound(0) + 1) <> 0) Then
    19. Dim p0 As IntPtr = Nothing
    20. p0 = Marshal.ReadIntPtr(p4)
    21. strBack = Marshal.PtrToStringAnsi(p0)
    22. End If
    23. Finally
    24. Marshal.FreeHGlobal(p1)
    25. Marshal.FreeHGlobal(p3)
    26. End Try
    27. End Sub
    28. End Module


    VB.NET-Quellcode

    1. <DllImport("Test.dll")> _
    2. Public Shared Function Test2(ByVal arr As IntPtr, ByVal arrR As IntPtr, ByVal iLenArr As Integer) As Integer
    3. End Function


    Für die Hilfe danke ich.

    Freundliche Grüsse

    exc-jdbi

    PS.
    Ich habe diese Anfrage in einem anderen Forum schon gestellt, und leider keine Antwort bekommen. Ich hoffe das ich hier Antwort bekomme. Sorry für mein Vorgehen.

    Auch möchte ich noch erwähnen das ich eine Lösung habe, in dem ich
    - String-Array in einen String umgewandelt habe, und so an die DLL übergeben
    - In der DLL den String wieder in eine Array umgewandelt habe.

    Ich erhoffe mir jedoch noch eine bessere / weitere Lösung zum Vorgehen hier zu bekommen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    Willkommen im Forum. :thumbup:
    Definiere

    exc-jdbi schrieb:

    eine ganz normale Array
    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!

    exc-jdbi schrieb:

    Multi-Char-Array
    Ein solches zweidimensionales Array kannst Du behandeln wie ein eindimensionales Array, da es "rechteckig" ist.
    Du musst nur die Dimensionen mit übergeben.
    Besser wäre es, wenn Du eine CLI-DLL machen würdest, da hast Du auf der (managed) C++-Seite sowohl .NET- als auch natrive C/C++-Datentypen.
    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!
    Ich muss leider auf einer "C-Dll" bleiben. Ist so vorgegeben.

    Das mit der eindimensionalen Array-Übergabe, ist genau das Problem das ich habe. Ich bring das nicht mit Inhalt in die vorgegebene Array und auch nicht wieder zurück.

    Ich glaube ich packe hier was vollkommen falsch an. Muss ich für die Übergabe einer Array eine Struktur nehmen, gleich wie in deinem Beispiel?

    Freundliche Grüsse

    exc-jdbi
    Probier das zunächst mit einem

    exc-jdbi schrieb:

    eindimensionalen Array
    .
    Char in .NET ist ein wchar_t (short, 2 Byte).
    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!
    Guten Abend RodFromGermany

    Ich versuche es jetzt einmal schrittweise.
    1. Zuerst eine Array aus der Dll und wenn das klappt
    2. eine Array übergeben

    Erstere mache ich so wie es unten steht

    Ich kriege aber nur chinesische Zeichen statt die in der Dll definierte
    "Ich" "bin" "eine" "Array"


    Freundliche Grüsse

    exc-jdbi

    Edit: Sorry habe deinen HInweis bezüglich UniCode zu spät gesehen, das war genau das Problem :thumbsup:
    Werde mich an die nächste Position machen



    C-Quellcode

    1. extern "C"
    2. __declspec(dllexport) BOOL _stdcall Test3(void **pArr){
    3. BOOL ret=false;
    4. std::vector<wchar_t*>vchArr;
    5. vchArr.push_back(L"Ich");
    6. vchArr.push_back(L"bin");
    7. vchArr.push_back(L"eine");
    8. vchArr.push_back(L"Array");
    9. int iSize= sizeof(wchar_t)*(4*5);
    10. wchar_t chArr[4][5];
    11. *pArr = (void*)GlobalAlloc(GHND,(size_t) iSize);
    12. for (int i=0;i<(int)vchArr.size();i++){
    13. for (int j = 0; j <(int)std::wcslen(vchArr[i]); j++){
    14. chArr[i][j] = vchArr[i][j];
    15. }
    16. }
    17. memcpy(*pArr, (void*)chArr,iSize);
    18. if(chArr[0][0]=='I'){ret=true;}
    19. return ret;
    20. }


    VB.NET-Quellcode

    1. <DllImport("dllArray.dll",
    2. CharSet:=CharSet.Auto,CallingConvention:=CallingConvention.StdCall)> _
    3. Public Shared Function Test3(ByRef arr As IntPtr) As Integer
    4. End Function



    VB.NET-Quellcode

    1. Dim strArrR() As String = {}
    2. p3 = IntPtr.Zero
    3. If (dll.Test3(p3) <> 0) Then
    4. Dim s() As Char
    5. Dim p0 As IntPtr = IntPtr.Zero
    6. strArrR = New String(3) {}
    7. For i As Integer = 0 To 3
    8. p0 = CType(p3 + (Marshal.SizeOf(GetType(Char)) * (5 * i)), IntPtr)
    9. s = New Char(4) {}
    10. Marshal.Copy(p0, s, 0, 5)
    11. For j As Integer = 0 To 4
    12. strArrR(i) += s(j)
    13. Next
    14. Next
    15. End If

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „exc-jdbi“ ()

    Guten Morgen

    Hab kurz Zeit gefunden, nochmals mich mit dem zu befassen.

    Leider funkst das immer noch nicht.

    Ich brauche einen Tip wie ich vorgehen muss, um eine Array (in diesem Fall wie im ersten Beitrag gezeigt eine char-Aaray) an die Dll zu übergeben.
    Das Problem ist, dass jeder Versuch den ich gemacht habe, immer nur eine Array ohne Inhalt überwiesen hat.

    Welche Vorbereitungen in Bezug auf IntPtr müssen zuerst gemacht werden, damit eine Array an eine Dll übergeben werden kann.

    Das müsste doch irgendwie so gehen


    Quellcode

    1. Dim sizePtr As Integer = Marshal.SizeOf(GetType(IntPtr))
    2. Dim sizeChar As Integer = Marshal.SizeOf(GetType(Char))
    3. 'Es geht mir nur einmal um die Übergabe einer Array
    4. Dim pTemp As IntPtr = Nothing
    5. p4 = Marshal.AllocCoTaskMem((chArr.GetUpperBound(0) + 1) * sizePtr) 'p4 ist eine IntPtr
    6. For i As Integer = 0 To chArr.GetUpperBound(0)
    7. pTemp = Marshal.AllocCoTaskMem((chArr.GetUpperBound(1) + 1) * sizeChar)
    8. Marshal.Copy(......)
    9. Marshal.WriteIntPtr(...)
    10. Next


    Oder ist dieser Ansatz komplett falsch? Wie müsst er dann aussehen?

    Danke für die Hilfe

    Freundliche Grüsse

    exc-jdbi
    Wenn es nur um die Übergabe von einem Array geht, kannst du auch MarshalAs benutzen.
    msdn.microsoft.com/de-de/library/z6cfh6e6(v=vs.110).aspx

    Hier sind ein paar Beispiel Codes für das Marshalling von Arrays (ByVal&ByRef): msdn.microsoft.com/en-us/library/hk9wyw21(v=vs.110).aspx

    Für C->C# Datentypen bzw. C# -> C: kobashicomputing.com/mapping-data-types-c-c-net
    "Zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber bei dem Universum bin ich mir noch nicht ganz sicher." Albert Einstein

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „hellmaster159“ ()

    Erklärungskonzept zu Marshalling von Array

    Das Erklärungskonzept

    VB.NET-Quellcode

    1. Dim strArrR() As String = {}
    2. Dim strArr() As String = New String() {"Ich", "bin", "eine", "Array"}
    3. Dim pStrA = Marshal.AllocCoTaskMem(Marshal.SizeOf(GetType(IntPtr)) * strArr.Length)
    4. Dim pStrB = Marshal.AllocCoTaskMem(Marshal.SizeOf(GetType(IntPtr)) * strArr.Length)
    5. Dim pTemp As IntPtr = IntPtr.Zero
    6. For i As Integer = 0 To strArr.Length - 1
    7. '16 bit entspricht Unicode (>> *2)
    8. pTemp = Marshal.AllocHGlobal( Marshal.SizeOf(GetType(Char)) * 2 * strArr(i).Length)
    9. Marshal.Copy(strArr(i).ToCharArray, 0, pTemp, strArr(i).Length)
    10. Marshal.WriteIntPtr(pStrA, i * Marshal.SizeOf(GetType(IntPtr)), pTemp)
    11. Marshal.WriteIntPtr(pStrB, i * Marshal.SizeOf(GetType(IntPtr)), CType(strArr(i).Length, IntPtr))
    12. Next
    13. 'Hier gehts zur z.B. DLL etc.
    14. 'Und wieder zurück (Sofern die gleiche Array genutzt wird)
    15. Dim s() As Char = {}
    16. Dim intLen As IntPtr = IntPtr.Zero
    17. Dim p0 As IntPtr = IntPtr.Zero
    18. ReDim strArrR(strArr.Length - 1)
    19. For i As Integer = 0 To strArr.Length - 1
    20. intLen = Marshal.ReadIntPtr(pStrB, i * Marshal.SizeOf(GetType(IntPtr)))
    21. p0 = Marshal.ReadIntPtr(pStrA, i * Marshal.SizeOf(GetType(IntPtr)))
    22. ReDim s(CInt(intLen) - 1)
    23. Marshal.Copy(p0, s, 0, CInt(intLen))
    24. strArrR(i) = s
    25. Next
    26. 'Darf nie vergessen werden
    27. Marshal.FreeHGlobal( pStrA)
    28. Marshal.FreeHGlobal(pStrB)
    29. etc.



    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    Guten Tag Community

    Ich möchte mich für alles Tips und Hinweise bedanken.

    Ziel erreicht, Thema erledit.

    Freundliche Grüsse

    exc-jdbi
    Dateien
    • Anhang.zip

      (2,31 kB, 247 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()