dll aus C in vb.net aufrufen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 129 Antworten in diesem Thema. Der letzte Beitrag () ist von tron25.

    @tron25 Häng mal das aktuelle Projekt mit der neuen DLL an (Bitte keine Zwischenstände).
    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!
    @tron25 Kannst SDu parallel dazu noch die alte Version bedienen?
    Ich weiß jetzt nicht, was da rauskommen soll.
    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!
    @tron25 Jou, das ganze ist ein wenig merkwürdig.
    Ich hab mal folgende Änderung vorgenommen:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. For Each Zeile In TextBox1.Text.Split(vbNewLine)
    3. Dim res = LouTranslator.Translate(Zeile)
    4. TextBox2.AppendText(res)
    5. TextBox2.AppendText(Environment.NewLine)
    6. Next
    7. End Sub

    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!
    @tron25 "Wochenende" bringt "ⷌ愼ս"
    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!
    @tron25 Jou.
    Dann stimmt irgendwas mit dem Aufruf nicht. ;(
    Nimm ggf. wieder die alte Version.
    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!
    Schaut man sich github.com/liblouis/liblouis/b…er/liblouis/liblouis.h.in an, fällt sofort der Unterschied zwischen

    C-Quellcode

    1. typedef unsigned short formtype;

    und

    C-Quellcode

    1. typedef enum {
    2. // [...]
    3. } typeforms;

    auf. Die Enumeration typeforms dient lediglich dazu, den Parameter typeform vom Typ formtype* elegant formulieren zu können. Laut Dokumentation ist das ein Arrayparameter mit dynamischer Größe:

    It is an array of formtype with the same length as the input buffer pointed to by *inbuf.


    Die neue Signatur der DLL-Funktion ist lou_translateString(const char*, const widechar*, int*, widechar*, int*, formtype*, char*, int).

    Die verwaltete Deklaration muss daher lauten:

    VB.NET-Quellcode

    1. 'int EXPORT_CALL lou_translateString
    2. '(const char *tableList,
    3. ' const widechar *inbuf,
    4. ' int *inlen,
    5. ' widechar * outbuf,
    6. ' int *outlen,
    7. ' formtype *typeform,
    8. ' char *spacing,
    9. ' int mode);
    10. <DllImport("liblouis-3.dll")>
    11. Public Shared Function lou_translateString(
    12. <MarshalAs(UnmanagedType.LPStr)> tableList As String,
    13. <MarshalAs(UnmanagedType.LPWStr)> inbuf As String,
    14. ByRef inlen As Int32,
    15. <MarshalAs(UnmanagedType.LPWStr), Out()> outbuf As StringBuilder,
    16. ByRef outlen As Int32,
    17. typeform() As Typeforms,
    18. <MarshalAs(UnmanagedType.LPStr)> spacing As String,
    19. mode As Int32) As Int32
    20. End Function
    21. Public Enum Typeforms As UShort
    22. plain_text = &H0
    23. italic = &H1 ' emph_1
    24. underline = &H2 ' emph_2
    25. bold = &H4 ' emph_3
    26. emph_4 = &H8
    27. emph_5 = &H10
    28. emph_6 = &H20
    29. emph_7 = &H40
    30. emph_8 = &H80
    31. emph_9 = &H100
    32. emph_10 = &H200
    33. computer_braille = &H400
    34. no_translate = &H800
    35. no_contract = &H1000
    36. End Enum

    Das Array wird automatisch in beide Richtungen gemarshallt. Der unverwaltete Pointer ist letztlich ein unsigned short*, weil die Enumeration mit As UShort deklariert wurde.

    Der Aufruf sieht so aus (Auszug):

    VB.NET-Quellcode

    1. ' [...]
    2. Dim buffer As New StringBuilder(refLength)
    3. Dim typeform() = Enumerable.Repeat(NativeMethods.Typeforms.plain_text, refLength).ToArray()
    4. NativeMethods.lou_translateString("tables\de-de-g2.ctb", input, input.Length, buffer, refLength, typeform, Nothing, 0)
    5. ' Limit stringBuilder size in case of implicit memory reallocation
    6. ' [...]

    Das funktioniert aber noch nicht, weil die neue Version der DLL auch neue Tabellen benötigt. Vergleiche z.B. die Versionen der Datei de-g0-core.uti, dann siehst du den Unterschied. Die "emphasis opcodes" haben sich unter anderem geändert. Abhilfe: Lade die neuen Tabellen vom GitHub-Projekt.

    Sehr hilfreich ist übrigens auch diese Funktion:

    VB.NET-Quellcode

    1. <DllImport("liblouis-3.dll")>
    2. Public Shared Sub lou_setLogLevel(level As Int32)
    3. End Sub
    4. ' Aufruf: NativeMethods.lou_setLogLevel(0)
    Gruß
    hal2000
    Ich habe die Änderungen durchgeführt. Nun bekomme ich folgende Fehlermeldung:

    Fehler BC32050 Der TResult-Typparameter für "Public Shared Overloads Function Repeat(Of TResult)(element As TResult, count As Integer) As IEnumerable(Of TResult)" kann nicht per Rückschluss abgeleitet werden.

    Das Programm markiert folgende Zeile:

    VB.NET-Quellcode

    1. Dim typeform() = Enumerable.Repeat(NativeMethods.Typeforms.plain_text, refLength).ToArray()
    Ich habe nun den Code erneut eingefügt:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    3. End
    4. End Sub
    5. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    6. For Each Zeile In TextBox1.Text.Split(vbNewLine)
    7. Dim res = LouTranslator.Translate(Zeile)
    8. TextBox2.AppendText(res)
    9. TextBox2.AppendText(Environment.NewLine)
    10. Next
    11. ' For Each Zeile In TextBox1.Text.Split(vbNewLine)
    12. ' TextBox2.AppendText(LouTranslator.Translate(Zeile) & Environment.NewLine)
    13. ' Next
    14. End Sub
    15. End Class


    und

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Imports System.Text
    3. Public Enum Typeforms As UShort
    4. plain_text = &H0
    5. italic = &H1 ' emph_1
    6. underline = &H2 ' emph_2
    7. bold = &H4 ' emph_3
    8. emph_4 = &H8
    9. emph_5 = &H10
    10. emph_6 = &H20
    11. emph_7 = &H40
    12. emph_8 = &H80
    13. emph_9 = &H100
    14. emph_10 = &H200
    15. computer_braille = &H400
    16. no_translate = &H800
    17. no_contract = &H1000
    18. End Enum
    19. Public Class LouTranslator
    20. Public Shared Function Translate(input As String) As String
    21. ' If String.IsNullOrEmpty(input) Then
    22. ' Throw New ArgumentNullException("input")
    23. ' End If
    24. Dim refLength As Int32 = input.Length + 32 ' size heuristic
    25. Dim buffer As New StringBuilder(refLength)
    26. Dim typeform() As NativeMethods.Typeforms = Enumerable.Repeat(Of NativeMethods.Typeforms)(NativeMethods.Typeforms.plain_text, refLength).ToArray()
    27. ' Limit stringBuilder size in case of implicit memory reallocation
    28. buffer.Length = refLength
    29. Return buffer.ToString()
    30. End Function
    31. End Class
    32. Public Class NativeMethods
    33. 'int EXPORT_CALL lou_translateString
    34. '(const char *tableList,
    35. ' const widechar *inbuf,
    36. ' int *inlen,
    37. ' widechar * outbuf,
    38. ' int *outlen,
    39. ' formtype *typeform,
    40. ' char *spacing,
    41. ' int mode);
    42. <DllImport("liblouis.dll")>
    43. Public Shared Function lou_translateString(
    44. <MarshalAs(UnmanagedType.LPStr)> tableList As String,
    45. <MarshalAs(UnmanagedType.LPWStr)> inbuf As String,
    46. ByRef inlen As Int32,
    47. <MarshalAs(UnmanagedType.LPWStr), Out()> outbuf As StringBuilder,
    48. ByRef outlen As Int32,
    49. typeform() As Typeforms,
    50. <MarshalAs(UnmanagedType.LPStr)> spacing As String,
    51. mode As Int32) As Int32
    52. End Function
    53. End Class


    Es erscheint immernoch die gleiche Fehlermeldung.
    @tron25 Hör auf mit dem LINQ, bau Dir die Liste zu Fuß zusammen!
    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!
    Die Enumeration "Typeforms" gehört in die Klasse NativeMethods - bei dir steht sie außerhalb.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Imports System.Text
    3. Module Module1
    4. Sub Main()
    5. Dim result = LouTranslator.Translate("Wochenende")
    6. End Sub
    7. End Module
    8. Class LouTranslator
    9. Public Shared Function Translate(input As String) As String
    10. If String.IsNullOrEmpty(input) Then
    11. Throw New ArgumentNullException("input")
    12. End If
    13. Dim refLength As Int32 = input.Length + 32 ' size heuristic
    14. Dim buffer As New StringBuilder(refLength)
    15. Dim typeform() = Enumerable.Repeat(NativeMethods.Typeforms.plain_text, refLength).ToArray()
    16. NativeMethods.lou_translateString("tables\de-de-g2.ctb", input, input.Length, buffer, refLength, typeform, Nothing, 0)
    17. ' Limit stringBuilder size in case of implicit memory reallocation
    18. buffer.Length = refLength
    19. Return buffer.ToString()
    20. End Function
    21. End Class
    22. Class NativeMethods
    23. 'int EXPORT_CALL lou_translateString
    24. '(const char *tableList,
    25. ' const widechar *inbuf,
    26. ' int *inlen,
    27. ' widechar * outbuf,
    28. ' int *outlen,
    29. ' formtype *typeform,
    30. ' char *spacing,
    31. ' int mode);
    32. <DllImport("liblouis-3.dll")>
    33. Public Shared Function lou_translateString(
    34. <MarshalAs(UnmanagedType.LPStr)> tableList As String,
    35. <MarshalAs(UnmanagedType.LPWStr)> inbuf As String,
    36. ByRef inlen As Int32,
    37. <MarshalAs(UnmanagedType.LPWStr), Out()> outbuf As StringBuilder,
    38. ByRef outlen As Int32,
    39. typeform() As Typeforms,
    40. <MarshalAs(UnmanagedType.LPStr)> spacing As String,
    41. mode As Int32) As Int32
    42. End Function
    43. Public Enum Typeforms As UShort
    44. plain_text = &H0
    45. italic = &H1 ' emph_1
    46. underline = &H2 ' emph_2
    47. bold = &H4 ' emph_3
    48. emph_4 = &H8
    49. emph_5 = &H10
    50. emph_6 = &H20
    51. emph_7 = &H40
    52. emph_8 = &H80
    53. emph_9 = &H100
    54. emph_10 = &H200
    55. computer_braille = &H400
    56. no_translate = &H800
    57. no_contract = &H1000
    58. End Enum
    59. End Class

    Gruß
    hal2000
    Vielen Dank. Es funktioniert jetzt.
    Hier nochmal der angepaßte Code:

    Die aufrufende Funktion:

    VB.NET-Quellcode

    1. GekuerztText.Text = ""
    2. For Each Zeile In UngekuerztText.Lines
    3. GekuerztText.AppendText(LouTranslator.Translate(Zeile) & Environment.NewLine)
    4. Next


    Und hier, der Code in der LibLouis-Klasse:

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Imports System.Text
    3. Class LouTranslator
    4. Public Shared Function Translate(input As String) As String
    5. If String.IsNullOrEmpty(input) Then
    6. Throw New ArgumentNullException("input")
    7. End If
    8. Dim refLength As Int32 = input.Length + 32 ' size heuristic
    9. Dim buffer As New StringBuilder(refLength)
    10. Dim typeform() = Enumerable.Repeat(NativeMethods.Typeforms.plain_text, refLength).ToArray()
    11. NativeMethods.lou_translateString("Braille\Brailletabellen\de-de-g2.ctb", input, input.Length, buffer, refLength, typeform, Nothing, 0)
    12. ' Limit stringBuilder size in case of implicit memory reallocation
    13. buffer.Length = refLength
    14. Return buffer.ToString()
    15. End Function
    16. End Class
    17. Class NativeMethods
    18. 'int EXPORT_CALL lou_translateString
    19. '(const char *tableList,
    20. ' const widechar *inbuf,
    21. ' int *inlen,
    22. ' widechar * outbuf,
    23. ' int *outlen,
    24. ' formtype *typeform,
    25. ' char *spacing,
    26. ' int mode);
    27. ' <DllImport("liblouis.dll")>
    28. <DllImport("liblouis.dll", BestFitMapping:=True, ThrowOnUnmappableChar:=True, CharSet:=CharSet.Unicode)>
    29. Public Shared Function lou_translateString(
    30. <MarshalAs(UnmanagedType.LPStr)> tableList As String,
    31. <MarshalAs(UnmanagedType.LPWStr)> inbuf As String,
    32. ByRef inlen As Int32,
    33. <MarshalAs(UnmanagedType.LPWStr), Out()> outbuf As StringBuilder,
    34. ByRef outlen As Int32,
    35. typeform() As Typeforms,
    36. <MarshalAs(UnmanagedType.LPStr)> spacing As String,
    37. mode As Int32) As Int32
    38. End Function
    39. Public Enum Typeforms As UShort
    40. plain_text = &H0
    41. italic = &H1 ' emph_1
    42. underline = &H2 ' emph_2
    43. bold = &H4 ' emph_3
    44. emph_4 = &H8
    45. emph_5 = &H10
    46. emph_6 = &H20
    47. emph_7 = &H40
    48. emph_8 = &H80
    49. emph_9 = &H100
    50. emph_10 = &H200
    51. computer_braille = &H400
    52. no_translate = &H800
    53. no_contract = &H1000
    54. End Enum
    55. End Class


    Vielen Dank nochmal an Alle.