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.

    dll aus C in vb.net aufrufen

    Hallo,

    ich schreibe ein Programm, mit dem man normalen Text in die Blindenkurzschrift übersetzen kann. Zu VB6-Zeiten habe ich die erste Version geschrieben. Damals stand ich vor dem gleichen Problem und habe es gelöst, indem ich vorcompilierte EXE-Dateien verwendet habe. Nun möchte ich es richtig machen und die C-DLL einbinden und die Funktionen direkt aus dem Programm heraus aufrufen. Das Programm schreibe ich in VB2015.

    Nun zum Programm:
    Es gibt die Textboxen "Ungekuerztztext" und "Gekuerzttext". In der ersten Textbox steht der ursprüngliche Text. Nach Aufruf der entsprechenden Funktion soll der gekürzte Text (eine Art von Stenographie) im zweiten Textfeld erscheinen. Die Funktion, die verwendet wird, erwartet neben den Textboxen und ihren Längen auch eine Übersetzungstabelle, in der die Abkürzungen und Regeln aufgelistet sind.

    Funktionsdeclaration in der DLL:

    C-Quellcode

    1. int EXPORT_CALL lou_translateString
    2. (const char *tableList,
    3. const widechar *inbuf,
    4. int *inlen,
    5. widechar * outbuf,
    6. int *outlen, char *typeform, char *spacing, int mode);


    Im VB-Programm habe ich folgenden Code stehen:

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. Private Declare Function lou_translateString Lib "liblouis-2.dll" (ByRef tableList As String, ByRef inbuf As String, inlen As Integer, outbuf As String, outlen As Integer, typeform As Byte, spacing As Byte, mode As Integer) As Integer
    4. Public Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. Programmverzeichnis = Application.StartupPath
    6. end sub
    7. Public Sub TextUebersetzen()
    8. lou_translateString(Programmverzeichnis & "\Braille\Brailletabellen\" & AktuelleUebersetzungstabelle, UngekuerztText.Text, Len(UngekuerztText.Text), GekuerztText.Text, Len(UngekuerztText.Text), 0, 0, 0)
    9. end sub
    10. End Class


    In der Variablen "AktuelleUebersetzungstabelle" steht der Dateiname der entsprechenden Übersetzungsdatei.

    Am Ende meines Beitrages füge ich die Beschreibung der Funktion "lou_translateString" hinzu.

    Ich habe hier im Forum schon gesucht und auch Beiträge gefunden. Soweit ich verstanden habe, muß man die Übergabeparameter mit "marshal..." umwandeln. Ich habe es aber leider noch nicht hinbekommen. Es wäre sehr nett, wenn Jemand den obigen Code umwandeln könnte. Vielleicht verstehe ich es anhand meines eigenen Codes dann besser.

    Vielen Dank schon einmal für eure Hilfe!

    P.S.: Ich möchte mich dafür entschuldigen, daß ich die Codeausschnitte nicht richtig formatiert habe, aber wenn man einen Screenreader verwendet, sind Formatierungen manchmal etwas schwierig.

    --> Edit by hal2000: Ich hab' das mal erledigt.

    Beschreibung von "lou_translateString":

    Spoiler anzeigen
    This function takes a string of 16-bit Unicode characters in `inbuf'
    and translates it into a string of 16-bit characters in `outbuf'. Each
    16-bit character produces a particular dot pattern in one braille cell
    when sent to an embosser or braille display or to a screen type font.
    Which 16-bit character represents which dot pattern is indicated by the
    character-definition and display opcodes in the translation table.

    The `tableList' parameter points to a list of translation tables
    separated by commas. If only one table is given, no comma should be
    used after it. It is these tables which control just how the
    translation is made, whether in Grade 2, Grade 1, or something else.

    liblouis knows where to find all the tables that have been
    distributed with it. So you can just give a table name such as
    `en-us-g2.ctb' and liblouis will load it. You can also give a table
    name which includes a path. If this is the first table in a list, all
    the tables in the list must be on the same path. You can specify a path
    on which liblouis will look for table names by setting the environment
    variable `LOUIS_TABLEPATH'. This environment variable can contain one or
    more paths separated by commas. On receiving a table name liblouis
    first checks to see if it can be found on any of these paths. If not,
    it then checks to see if it can be found in the current directory, or,
    if the first (or only) name in a table list, if it contains a path
    name, can be found on that path. If not, it checks to see if it can be
    found on the path where the distributed tables have been installed. If
    a table has already been loaded and compiled this path-checking is
    skipped.

    The tables in a list are all compiled into the same internal table.
    The list is then regarded as the name of this table. As explained in
    *Note How to Write Translation Tables::, each table is a file which may
    be plain text, big-endian Unicode or little-endian Unicode. A table (or
    list of tables) is compiled into an internal representation the first
    time it is used. Liblouis keeps track of which tables have been
    compiled. For this reason, it is essential to call the `lou_free'
    function at the end of your application to avoid memory leaks. Do _NOT_
    call `lou_free' after each translation. This will force liblouis to
    compile the translation tables each time they are used, leading to
    great inefficiency.

    Note that both the `*inlen' and `*outlen' parameters are pointers to
    integers. When the function is called, these integers contain the
    maximum input and output lengths, respectively. When it returns, they
    are set to the actual lengths used.

    The `typeform' parameter is used to indicate italic type, boldface
    type, computer braille, etc. It is a string of characters with the same
    length as the input buffer pointed to by `*inbuf'. However, it is used
    to pass back character-by-character results, so enough space must be
    provided to match the `*outlen' parameter. Each character indicates
    the typeform of the corresponding character in the input buffer. The
    values are as follows: 0 plain-text; 1 italic; 2 bold; 4 underline; 8
    computer braille. These values can be added for multiple emphasis. If
    this parameter is `NULL', no checking for type forms is done. In
    addition, if this parameter is not `NULL', it is set on return to have
    an 8 at every position corresponding to a character in `outbuf' which
    was defined to have a dot representation containing dot 7, dot 8 or
    both, and to 0 otherwise.

    The `spacing' parameter is used to indicate differences in spacing
    between the input string and the translated output string. It is also
    of the same length as the string pointed to by `*inbuf'. If this
    parameter is `NULL', no spacing information is computed.

    The `mode' parameter specifies how the translation should be done.
    The valid values of mode are listed in `liblouis.h'. They are all
    powers of 2, so that a combined mode can be specified by adding up
    different values.

    The function returns 1 if no errors were encountered and 0 if a
    complete translation could not be done.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „hal2000“ ()

    tron25 schrieb:

    die C-DLL einbinden und die Funktionen direkt aus dem Programm heraus aufrufen
    Gugst Du hier.
    Lade die Projekte runter und probiere sie aus.
    Wenn Du die Quellen der DLL hast, füge das DLL-Projekt der Projektmappe Deines VB-Hauptprogramms hinzu.
    Sieh Dir in meinem Testprojekt die Projektsettings an.
    Sieh Dir die Parameterdeklaration auf beiden Seiten (.NET und native DLL) an und pass ggf. Deine Parameter an.
    Informiere Dich über die Marshal-Klasse.
    Und zuletzt: Viel Spaß. :thumbsup:
    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,

    vielen Dank für die schnelle Antwort. Die Programme habe ich mir angeschaut, aber sie sind mir etwas zu kompliziert. Leider bin ich derzeit ziemlich im Zeitdruck, daher habe ich das Problem, wie früher, mit den schon kompilierten EXE-Dateien gelöst. Wenn ich mal viel Zeit habe, werde ich mir deine Programme erneut anschauen.

    Noch einmal vielen Dank

    Gruß

    tron225
    Wenn ich noch etwas anmerken darf: Du verwendest noch den alten VB6 Style (Private Declare Function ...). Das wird heute (mit VB.NET) über das Attribut DllImport aus dem Namespace System.Runtime.InteroptServices gelöst. Hier eine kleine Anleitung.
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Hallo,

    irgendwie läßt es mir doch keine Ruhe. Ich habe meinen Code nun folgendermaßen angepaßt:

    Deklaration:
    <DllImport("liblouis-2.dll", EntryPoint:="lou_translateString")> Private Shared Function lou_translateString(<MarshalAs(UnmanagedType.LPStr)> ByRef tableList As String, <MarshalAs(UnmanagedType.LPStr)> ByRef inbuf As String, ByRef inlen As Integer, <MarshalAs(UnmanagedType.LPStr)> outbuf As String, outlen As Integer, typeform As Byte, spacing As Byte, mode As Integer) As Integer
    End Function

    Ich habe oft gelesen, daß am Ende der ersten Deklarationszeile ein "_" geschrieben wird, damit es in der nächsten Zeile weitergehen kann. Mein "_" verschwindet dabei immer wieder. Daher habe ich das Ganze in eine Zeile gepackt.

    Aufruf:
    If lou_translateString(Programmverzeichnis & "\Braille\Brailletabellen\" & AktuelleUebersetzungstabelle, UngekuerztText.Text, Len(UngekuerztText.Text), GekuerztText.Text, Len(UngekuerztText.Text), 0, 0, 0) = 0 Then
    Me.Text = "Fehler"
    Else
    Me.Text = "Korrekt"
    End If

    Leider funktioniert es nicht. Wie muß ich die Variablen konvertieren, damit sie in der DLL als WideChar ankommen?

    tron25 schrieb:

    daß am Ende der ersten Deklarationszeile ein "_" geschrieben wird, damit es in der nächsten Zeile weitergehen kann
    Das ist VB spezifisch. Das hat den Vorteil, dass du eine Zuweisung auch in mehreren Zeilen (der Übersichtlichkeit halber) schreiben kannst

    tron25 schrieb:

    Mein "_" verschwindet dabei immer wieder.
    Ist normal

    Zu dem String:
    Probier mal UnmanagedType.LPWStr
    msdn.microsoft.com/de-de/library/s9ts558h(v=vs.110).aspx
    stackoverflow.com/questions/16…-to-unicode-string-vb-net

    Lg Radinator

    PS: Und bitte verwende Code Tags...das kann ja keiner lesen ;D
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    sicher, dass es WStrings sind und nicht einfach nur Unicode?
    Du kannst z.B. das CharSet beim DllImport setzen. Evlt. musst du im auch die CallingConvention klar machen.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Die Deklaration sieht nun folgendermaßen aus:

    <DllImport("liblouis-2.dll", EntryPoint:="lou_translateString")>
    Private Shared Function lou_translateString(<MarshalAs(UnmanagedType.LPStr)> ByRef tableList As String,
    <MarshalAs(UnmanagedType.LPWStr)> ByRef inbuf As String, ByRef inlen As Integer,
    <MarshalAs(UnmanagedType.LPWStr)> outbuf As String, outlen As Integer,
    typeform As Byte, spacing As Byte, mode As Integer) As Integer
    End Function

    Leider funktioniert es immer noch nicht.

    Ich habe versucht, den Code hier etwas besser zu formatieren. Leider weiß ich nicht, wie Tags gesetzt werden können. Dazu muß ich sagen, daß ich blind bin und mit einem Screenreader mit einer Braillezeile arbeite. Der Screenreader analysiert den Bildschirminhalt und gibt ihn über eine Sprachausgabe und eine Braillezeile wieder. Eine Braillezeile stellt das Gesprochene in Brailleschrift dar.
    outbuf würde ich lieber nen StringBuilder nehmen, outlen muss ByRef sein, ebenso typeform und spacing.
    CallingConvention und CharSet hast du immer noch nicht probiert.
    Im Editor gibt es extra einen Button für die Tags...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    tron25 schrieb:

    Leider weiß ich nicht, wie Tags gesetzt werden können.
    Wie @jvbsl gesagt hat: Für die Code Tags gibt es über dem Text, den du hier schreibst eine Box mit verschiedenen Buttons. Wenn du z.B auf den Button mtit der Aufschrift VB.NET clickst, erscheint an der Stelle, an der sich der Cursor befindet, ein Text[vbnet][/vbnet] dazwischen kannst du dann VB.NET Code eintragen, der wird dann (mehr oder minder) richtig syntax-gehighlighted.
    Am besten den Code direkt aus VS rauskopieren.

    Und was deine Fuktion betrifft: Mir war, als müsste man P/Invoke Funktionen als Public markieren. Bzw: Was genau geht nicht? Stet bei dir in outbuf einfach nix drinnen?
    Lg Radinator
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Ich habe mir nochmal die Beschreibung für "charset" und "callingconvention" durchgelesen und folgender Code ist dabei herausgekommen:

    Deklaration:
    <DllImport("liblouis-2.dll", EntryPoint:="lou_translateString", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.StdCall)>
    Public Shared Function lou_translateString(<MarshalAs(UnmanagedType.LPStr)> ByRef tableList As String, <MarshalAs(UnmanagedType.LPWStr)> ByRef inbuf As StringBuilder, ByRef inlen As Integer, <MarshalAs(UnmanagedType.LPWStr)> ByRef outbuf As StringBuilder, ByRef outlen As Integer, ByRef typeform As Byte, ByRef spacing As Byte, mode As Integer) As Integer
    End Function

    Aufruf:
    If lou_translateString(Programmverzeichnis & "\Braille\Brailletabellen\" & AktuelleUebersetzungstabelle, UngekuerztText.Text, Len(UngekuerztText.Text), GekuerztText.Text, Len(UngekuerztText.Text), 0, 0, 0) = 0 Then
    Me.Text = "Fehler"
    Else
    Me.Text = "Korrekt"
    End If

    Ich bekomme die Fehlermeldung:
    "Der Wert vom Typ "String" kann nicht in "StringBuilder" konvertiert werden.

    Wenn ich die Datentypen wieder in "String" ändere, bekomme ich "Fehler" in der Titelleiste angezeigt.

    Leider bekomme ich das mit den Tags nicht hin. Der Screenreader kann die Attribute nicht anspringen. Wenn ich mit der Maus über die Eigenschaften fahre, werden sie mir zwar angesagt, aber leider tut sich nichts, nachdem ich darauf geklickt habe. Sorry nochmal.

    tron25 schrieb:

    folgender Code ist dabei herausgekommen:
    Welcher Code? Ich sehe da nur einen Text. Keine Formatierung, keine Codetags. Lösung: Siehe ganz unten.

    Ich hab das ganze jetzt mal formatiert:

    VB.NET-Quellcode

    1. <DllImport("liblouis-2.dll", EntryPoint:="lou_translateString", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.StdCall)>
    2. Public Shared Function lou_translateString(
    3. <MarshalAs(UnmanagedType.LPStr)> ByRef tableList As String,
    4. <MarshalAs(UnmanagedType.LPWStr)> ByRef inBuf As StringBuilder,
    5. ByRef inLen As Integer,
    6. <MarshalAs(UnmanagedType.LPWStr)> ByRef outBuf As StringBuilder,
    7. ByRef outlen As Integer,
    8. ByRef typeform As Byte,
    9. ByRef spacing As Byte,
    10. ByVal mode As Integer
    11. ) As Integer
    12. End Function
    13. Dim pfad As String = Path.Combine(Programmverzeichnis, "Braille\Brailletabellen", AktuelleUebersetzungstabelle )
    14. Dim ungekuerzterText As string = UngekuerztText.Text
    15. Dim gekuerzterText As String = GekuerztText.Text
    16. Dim length1 As Integer = Len(ungekuerzterText)
    17. Dim result as Integer = lou_translateString(path, ungekuerzterText, length1, gekuerzterText, length1, 0, 0, 0)
    18. If = 0 Then
    19. Me.Text = "Fehler"
    20. Else
    21. Me.Text = "Korrekt"
    22. End If


    tron25 schrieb:

    Ich bekomme die Fehlermeldung:
    Wo steht diese Fehlermeldung? In einem Exception Fenster oder im Ausgabe Fenster?

    Ich hab mal nach PInvoke und Stringbuilder gegoogelt:
    Link1
    Link2
    So wie es aussieht, musst du den Stringbuilder mit einer Kapazität instanziieren. Sprich: Du musst im Konstruktor angeben (als integer), wie lange (also wie viele Zeichen maximal) das Ergebnis lange ist. Das verhindert Overflows.

    tron25 schrieb:

    Leider bekomme ich das mit den Tags nicht hin.
    https://www.vb-paradise.de/index.php/Thread/75192-Forum-Wie-f%C3%BCge-ich-Quellcode-korrekt-im-Forum-ein/

    Lg Radinator

    Edit:
    "Der Wert vom Typ "String" kann nicht in "StringBuilder" konvertiert werden.
    *facepalm* Hätt auch gleich drauf kommen können *eye-roll*.
    Was du hier machen willst (versuchst) ist: Du gibst an, dass die Funktion lou_translateString als zweiten und dritten Parameter einen Stringbuilder bekommt. Gibst aber im Aufruf deiner Methode jeweils einen String an. Das kann nicht gehen, nicht mal mit Option Strict Off. Außerdem - wie in Link1 oder Link2 besagt, brauchst du nur für einen __OUT__ char* einen Stringbuilder verwenden. Also als Ausgabe. Für die Eingabe reicht dir im normalfall ein UnmanagedType.LPStr oder ein UnmanagedType.LPWStr
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell

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

    Sieht die Formatierung nun besser aus? Ich füge jetz die Tags manuell hinzu.

    Der Code sieht nun so aus:

    VB.NET-Quellcode

    1. <DllImport("liblouis-2.dll", EntryPoint:="lou_translateString", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.StdCall)>
    2. Public Shared Function lou_translateString(
    3. <MarshalAs(UnmanagedType.LPStr)> ByRef tableList As String,
    4. <MarshalAs(UnmanagedType.LPWStr)> ByRef inBuf As String,
    5. ByRef inLen As Integer,
    6. <MarshalAs(UnmanagedType.LPWStr)> ByRef outBuf As StringBuilder,
    7. ByRef outlen As Integer,
    8. ByRef typeform As Byte,
    9. ByRef spacing As Byte,
    10. ByVal mode As Integer
    11. ) As Integer
    12. End Function
    13. Dim pfad As String = Path.Combine(Programmverzeichnis, "Braille\Brailletabellen", AktuelleUebersetzungstabelle )
    14. Dim ungekuerzterText As string = UngekuerztText.Text
    15. Dim gekuerzterText As String = GekuerztText.Text
    16. Dim length1 As Integer = Len(ungekuerzterText)
    17. Dim result as Integer = lou_translateString(pfad, ungekuerzterText, length1, gekuerzterText, length1, 0, 0, 0)
    18. If result = 0 Then
    19. Me.Text = "Fehler"
    20. Else
    21. Me.Text = "Korrekt"
    22. End If


    Ich habe folgende Kleinigkeiten geändert:
    <MarshalAs(UnmanagedType.LPWStr)> ByRef inBuf As String,
    Hier habe ich StringBuilder mit String ausgetauscht.

    Dim result as Integer = lou_translateString(path, ungekuerzterText, length1, gekuerzterText, length1, 0, 0, 0)
    Hier habe ich Pad mit Pfad ausgetauscht.

    if = 0 then
    Hier habe ich result eingefügt.

    Das Programm startet erst nicht. Unten im Ausgabefenster erscheint die folgende Meldung:
    Schweregrad Code Beschreibung Projekt Datei Zeile Unterdrückungszustand
    Fehler BC30311 Der Wert vom Typ "String" kann nicht in "StringBuilder" konvertiert werden. PunktBilder D:\Programmierung\PunktBilder\PunktBilder 2016\PunktBilder\PunktBilder\PunktbilderFormular.vb 563 Aktiv

    Wie kann ich die Länge im Construktor mit angeben?
    Zeile 3/4/6 nicht als ByRef. char ist ein einzelnes character char* ist ein ptr zu einem character(oftmals und auch hier das erste Zeichen einer Zeichenkette - string ist eine Zeichenkette und StringBuilder hält eine Zeichenkette).

    Dein "gekuerzterText" sollte - wie die Fehlermeldung schon sagt - kein String, sondern ein StringBuilder sein.

    Len sollte man seid 1945 nicht mehr verwenden. verwende "xyz".Length
    aber deine length1 sollte in diesem fall die Capacity des StringBuilders sein.

    Bist du dir außerdem sicher, dass es ein stdcall ist? Die werden meiner Erfahrung nach eher selten verwendet.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    So, nun bekomme ich zwar keine Fehlermeldung mehr, aber ich bekomme auch keinen gekürzten Text.

    VB.NET-Quellcode

    1. <DllImport("liblouis-2.dll", EntryPoint:="lou_translateString", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.StdCall)>
    2. Public Shared Function lou_translateString(
    3. <MarshalAs(UnmanagedType.LPArray)> tableList As Char(),
    4. <MarshalAs(UnmanagedType.LPArray)> inBuf As Char(),
    5. ByRef inLen As Integer,
    6. <MarshalAs(UnmanagedType.LPArray)> outBuf As Char(),
    7. ByRef outlen As Integer,
    8. ByRef typeform As Byte,
    9. ByRef spacing As Byte,
    10. ByVal mode As Integer
    11. ) As Integer
    12. End Function
    13. Dim pfad As String = Path.Combine(Programmverzeichnis, "Braille\Brailletabellen", AktuelleUebersetzungstabelle)
    14. Dim ungekuerzterText As String = UngekuerztText.Text
    15. Dim gekuerzterText As String = GekuerztText.Text
    16. Dim length1 As Integer = ungekuerzterText.Length
    17. Dim result As Integer = lou_translateString(pfad, ungekuerzterText, length1, gekuerzterText, length1, 0, 0, 0)
    18. lou_translateString(pfad, ungekuerzterText, length1, gekuerzterText, length1, 0, 0, 0)
    19. If result = 0 Then
    20. GekuerztText.Text = "Fehler"
    21. Else
    22. GekuerztText.Text = gekuerzterText
    23. End If



    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „tron25“ ()

    Du hast auch nichts von dem was ich gesagt umgesetzt, wie ich es wollte. jetzt hast du plötzlich char arrays, und konvertierst mittels "Option Strict Off" - was böse ist - implizit von Strings.

    Dein Vorheriger Code war näher dran, nur die genannten ByRefs weg. Und einen StringBuilder verwenden.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    tron25 schrieb:

    Ich füge jetz die Tags manuell hinzu.
    Ich fühle mich ein wenig veräppelt...hab ich dir doch in schon in Post #10 gesagt, was du machen musst. Einfach in dem gott verdammten Editor ÜBER dem Text, den schreibt AUF den Button mit der Aufschrift VB.NET klicken. Dann wird an der Stelle an der sich der Curso im Momen befindet der Text[vbnet][/vbnet] eingetragen. Dazwischen kannst du dann deine Quellcode aus Visual Studio aus rein kopieren.
    Übrigens: Auch wenn du nur eine einzelne Zeile Code hast, bitte die auch formatieren. Dann kann man das ganze wenigstens besser lesen ;D

    tron25 schrieb:

    Wie kann ich die Länge im Construktor mit angeben?
    Naja in dem du im Konstruktor aufruf einfach die Größte angibst?

    Lg Radinator
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Meintest du es so?

    VB.NET-Quellcode

    1. <DllImport("liblouis-2.dll", EntryPoint:="lou_translateString", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl l)>
    2. Public Shared Function lou_translateString(
    3. <MarshalAs(UnmanagedType.LPArray)> tableList As String,
    4. <MarshalAs(UnmanagedType.LPArray)> inBuf As String,
    5. ByRef inLen As Integer,
    6. <MarshalAs(UnmanagedType.LPArray)> outBuf As StringBuilder,
    7. ByRef outlen As Integer,
    8. ByRef typeform As Byte,
    9. ByRef spacing As Byte,
    10. ByVal mode As Integer
    11. ) As Integer
    12. End Function
    13. Dim pfad As String = Path.Combine(Programmverzeichnis, "Braille\Brailletabellen", AktuelleUebersetzungstabelle)
    14. Dim ungekuerzterText As String = UngekuerztText.Text
    15. Dim gekuerzterText As String = GekuerztText.Text
    16. Dim length1 As Integer = gekuerzterText.Length
    17. Dim result As Integer = lou_translateString(pfad, ungekuerzterText, length1, gekuerzterText, length1, 0, 0, 0)
    18. lou_translateString(pfad, ungekuerzterText, length1, gekuerzterText, length1, 0, 0, 0)
    19. If result = 0 Then
    20. GekuerztText.Text = "Fehler"
    21. Else
    22. GekuerztText.Text = gekuerzterText
    23. End If


    Ich bekomme folgende Fehlermeldung:
    Schweregrad Code Beschreibung Projekt Datei Zeile Unterdrückungszustand
    Fehler BC30311 Der Wert vom Typ "String" kann nicht in "StringBuilder" konvertiert werden. PunktBilder D:\Programmierung\PunktBilder\PunktBilder 2016\PunktBilder\PunktBilder\PunktbilderFormular.vb 563 Aktiv

    Als fehlerhafte Zeile wird mir folgende markiert:
    Dim result As Integer = lou_translateString(pfad, ungekuerzterText, length1, gekuerzterText, length1, 0, 0, 0)

    Ich dachte, daß ein StringBuilder eine Art von Array sei. Da lag ich wohl falsch.

    Entweder bin ich zu doof dafür, oder es wird Zeit, daß ich langsam in Rente gehe ;-).

    Unabhängig vom Ergebnis meines Problems möchte ich mich bei euch herzlich für eure Hilfe und Geduld bedanken.
    Ein StringBuilder ist eine Klasse. So wie - meinetwegen - die Klasse Form aus dem Namespace System.Windows.Forms. Da du dich hier (mit Visual Basic .NET) in einer objekt orientierten Sprache bewegest, musst du zuerst ein Objekt erzeugen. Diese kannst du dann an die Funktion übergeben.

    Probier einfach mal folgendes aus:

    VB.NET-Quellcode

    1. <DllImport(
    2. "liblouis-2.dll",
    3. EntryPoint:="lou_translateString",
    4. CharSet:=CharSet.Ansi,
    5. CallingConvention:=CallingConvention.Cdecll
    6. )>
    7. Public Shared Function lou_translateString(
    8. <MarshalAs(UnmanagedType.LPStr)> tableList As String,
    9. <MarshalAs(UnmanagedType.LPWStr)> inBuf As String,
    10. ByRef inLen As Integer,
    11. <MarshalAs(UnmanagedType.LPWStr)> outBuf As StringBuilder,
    12. ByRef outlen As Integer,
    13. ByRef typeform As Byte,
    14. ByRef spacing As Byte,
    15. ByVal mode As Integer
    16. ) As Integer
    17. End Function
    18. Dim pfad As String = -
    19. Path.Combine(
    20. Programmverzeichnis,
    21. "Braille\Brailletabellen",
    22. AktuelleUebersetzungstabelle
    23. )
    24. Dim ungekuerzterText As String = UngekuerztText.Text
    25. Dim gekuerzterText As String = GekuerztText.Text
    26. Dim length1 As Integer = gekuerzterText.Length
    27. Dim sb As New StringBuilder(length1)
    28. Dim result As Integer = lou_translateString(pfad, ungekuerzterText, length1, sb, length1, 0, 0, 0)
    29. If result = 0 Then
    30. GekuerztText.Text = "Fehler"
    31. Else
    32. GekuerztText.Text = gekuerzterText
    33. End If

    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Ich sehe hier noch folgendes Problem:

    VB.NET-Quellcode

    1. Dim gekuerzterText As String = GekuerztText.Text ' Leere Textbox für das Ergebnis
    2. Dim length1 As Integer = gekuerzterText.Length ' 0
    3. Dim sb As New StringBuilder(length1) ' StringBuilder mit Capacity = 0
    4. Dim result As Integer = lou_translateString(pfad, ungekuerzterText, length1, sb, length1, 0, 0, 0) ' Fail, weil der SB zu klein ist
    5. If result = 0 Then
    6. GekuerztText.Text = "Fehler" ' Fehler!
    7. Else
    8. GekuerztText.Text = gekuerzterText ' soll wohl sb.ToString() sein.
    9. End If

    Ich kenne einige C-Funktionen, die beim ersten Aufruf mit einem leeren Puffer die erforderliche Länge aus-/zurückgeben, damit im zweiten Aufruf der korrekt dimensionierte Buffer übergeben werden kann.
    Gruß
    hal2000