Wie am besten aus fertigem Beispiel, das in C geschrieben wurde, eine dll schreiben

  • C

Es gibt 37 Antworten in diesem Thema. Der letzte Beitrag () ist von chris_2091.

    Wie am besten aus fertigem Beispiel, das in C geschrieben wurde, eine dll schreiben

    Hallo zusammen,

    ich möchte für eine Sensoransteuerung(IMU-Sensor) eine dll schreiben, sodass man die Funktionen wie Daten senden, Daten anfordern usw. einfach nur in die GUI rein importieren muss und die gleichen Funktionen für mehrere Programme nutzen kann.
    Der Hersteller hat eine Beispiele mit Code mitgeliefert, die alle in C geschrieben sind. Daher wollte ich die meisten Daten einfach verwenden. Ich habe ein sehr gutes Beispiel gefunden, wo erklärt wird wie man eine C-dll in VB nutzen kann. Austausch von Daten zwischen einer VB.NET-exe und einer C-DLL, 32 und 64 Bit

    Als erstes wollte ich ein Beispiel eines Herstellers übernehmen und in eine Funktion packen, sodass ich das Beispiel aus meiner VB-Gui aus starten kann.
    Dazu habe ich alle Header-Files genommen, die auch im Beispiel vorkammen, eingebunden und auch die Header-Files geöffnet und da entsprechend die #include Befehle angepasst. Hier der Code des cpp-Files

    C-Quellcode

    1. /*
    2. * Copyright(c) 2009 - 2013, Hillcrest Laboratories, Inc.
    3. * All rights reserved.
    4. */
    5. #include "include/freespace/freespace.h"
    6. #include "include/freespace/freespace_codecs.h"
    7. #include "include/freespace/freespace_common.h"
    8. #include "include/freespace/freespace_deviceTable.h"
    9. #include "include/freespace/freespace_printers.h"
    10. #include "include/freespace/freespace_util.h"
    11. #include "appControlHandler.h"
    12. #include <string.h>
    13. #include "stdafx.h"
    14. #ifdef _WIN32
    15. #include "WIN32\stdafx.h"
    16. #else
    17. #include <stdio.h>
    18. #include <stdlib.h>
    19. #endif
    20. // Cross platform sleep macro
    21. #ifdef _WIN32
    22. #define SLEEP Sleep(200)
    23. #else
    24. #include <unistd.h>
    25. #define SLEEP sleep(1)
    26. #endif
    27. #define EXPORT32 extern "C" __declspec(dllexport)
    28. FreespaceDeviceId device; // Keep track of the device you are talking to
    29. struct freespace_message send; // A place to create messages to send to the device
    30. struct freespace_message receive; // A place to put a message received from the device
    31. int numIds; // Keep track of how many devices are available
    32. int rc; // Return Code
    33. int retryCount = 0; // How many times tried so far to get a response
    34. // Flag to indicate that the application should quit
    35. // Set by the control signal handler
    36. int quit = 0;
    37. // Limit on how many times to try to get a response
    38. #define RETRY_COUNT_LIMIT 100
    39. EXPORT32 int _stdcall TestFunction()
    40. // einfacher Aufruf einer Prozedur
    41. {
    42. addControlHandler(&quit);
    43. // Initialize the freespace library
    44. rc = freespace_init();
    45. if (rc != FREESPACE_SUCCESS) {
    46. //printf("Initialization error. rc=%d\n", rc);
    47. return 1;
    48. }
    49. //printf("Scanning for Freespace devices...\n");
    50. // Get the ID of the first device in the list of availble devices
    51. rc = freespace_getDeviceList(&device, 1, &numIds);
    52. if (numIds == 0) {
    53. //printf("Didn't find any devices.\n");
    54. return 1;
    55. }
    56. //printf("Found a device. Trying to open it...\n");
    57. // Prepare to communicate with the device found above
    58. rc = freespace_openDevice(device);
    59. if (rc != FREESPACE_SUCCESS) {
    60. //printf("Error opening device: %d\n", rc);
    61. return 1;
    62. }
    63. // Display the device information.
    64. printDeviceInfo(device);
    65. // Make sure any old messages are cleared out of the system
    66. rc = freespace_flush(device);
    67. if (rc != FREESPACE_SUCCESS) {
    68. //printf("Error flushing device: %d\n", rc);
    69. return 1;
    70. }
    71. //printf("Requesting battery level messages.\n");
    72. memset(&send, 0, sizeof(send)); // Start with a clean message struct
    73. // Populate the message fields. Two options are shown below. Uncomment one desired
    74. // and comment out the one not desired.
    75. //send.messageType = FREESPACE_MESSAGE_BATTERYLEVELREQUEST; // To send a battery level request
    76. send.messageType = FREESPACE_MESSAGE_PRODUCTIDREQUEST; // To send a product ID request
    77. while (!quit) {
    78. if (retryCount < RETRY_COUNT_LIMIT) {
    79. retryCount++;
    80. // Send the message constructed above.
    81. rc = freespace_sendMessage(device, &send);
    82. if (rc != FREESPACE_SUCCESS) {
    83. //printf("Could not send message: %d.\n", rc);
    84. }
    85. // Read the response message.
    86. rc = freespace_readMessage(device, &receive, 100);
    87. if (rc == FREESPACE_SUCCESS) {
    88. // Print the received message
    89. freespace_printMessage(stdout, &receive);
    90. retryCount = 0;
    91. }
    92. else if (rc == FREESPACE_ERROR_TIMEOUT) {
    93. //printf("<timeout> Try moving the Freespace device to wake it up.\n");
    94. }
    95. else if (rc == FREESPACE_ERROR_INTERRUPTED) {
    96. //printf("<interrupted>\n");
    97. }
    98. else {
    99. /*printf("Error reading: %d. Quitting...\n", rc);*/
    100. break;
    101. }
    102. }
    103. else {
    104. /*printf("Did not receive response after %d trials\n", RETRY_COUNT_LIMIT);*/
    105. quit = 1;
    106. }
    107. SLEEP;
    108. }
    109. /*printf("Cleaning up...\n");*/
    110. freespace_closeDevice(device);
    111. freespace_exit();
    112. return 0;
    113. }

    Zu einem bekomme ich den Fehler, bei der Zeile

    C-Quellcode

    1. FreespaceDeviceId device;

    Error C2146 syntax error: missing ';' before identifier 'device' MFCLibrary1 U:\GUI_Visual_Basic\MFCLibrary1\MFCLibrary1\Sensoransteuerung.cpp 50

    Ansonsten den gleichen Fehler (nur die Zeile ist immer anders)
    Error (active) redeclaration cannot add dllexport/dllimport to "WSASetLastError" (declared at line 873 of "c:\Program Files (x86)\Windows Kits\8.1\Include\um\winsock.h") MFCLibrary1 c:\Program Files (x86)\Windows Kits\8.1\Include\um\WinSock2.h 2407

    Ich danke euch schonmal im Voraus!!

    * Thema verschoben *

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

    Du inkludierst stdafx.h zweimal. Einmal aus deinem Projekt (Zeile 13) und einmal aus dem Beispiel (Zeile 16). Entferne Zeile 13 - das sollte den Fehler mit der Neudeklaration lösen. Das GIT-Repository für die Library ist unvollständig - daher kann ich das Problem hier nicht nachstellen. Es fehlen die Dateien für

    C-Quellcode

    1. #include "include/freespace/freespace_codecs.h"
    2. #include "include/freespace/freespace_printers.h"


    Edit: CMake muss durchlaufen. Dann sind auch alle Dateien vorhanden.
    Gruß
    hal2000

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

    Mit den zusätzlichen Dateien läuft der Build bei mir durch, mal abgesehen von Linkerfehlern, weil ich mir das Binary der Library nicht erstellt habe. Folgendes habe ich geändert:

    C-Quellcode

    1. #include "stdafx.h" // Muss die erste nicht-Kommentarzeile sein
    2. #ifdef _WIN32
    3. #include "WIN32\stdafx.h" // eigentlich unnötig
    4. #else
    5. #include <stdio.h>
    6. #include <stdlib.h>
    7. #endif
    8. // [...]


    Datei stdafx.h (aus dem Projekt, nicht aus dem Ordner WIN32)

    C-Quellcode

    1. // [...]
    2. // TODO: Hier auf zusätzliche Header, die das Programm erfordert, verweisen.
    3. #include "include/freespace/freespace.h"
    4. #include "include/freespace/freespace_codecs.h"
    5. #include "include/freespace/freespace_common.h"
    6. #include "include/freespace/freespace_deviceTable.h"
    7. #include "include/freespace/freespace_printers.h"
    8. #include "include/freespace/freespace_util.h"
    9. #include "appControlHandler.h"
    10. #include <string.h>


    Der vorkompilierte Header ist manchmal nervig - stackoverflow.com/questions/12…h-from-the-root-directory:
    When compiling a .cpp file that uses a PCH, VS expects the first non-comment/whitespace text to be #include "PCH_NAME_HERE". The PCH_NAME_HERE is exactly the PCH's name. No directories, nothing. Just the PCH's name as specified in the compiler options.

    --> WIN32\stdafx.h wird zum normalen Include, sodass er den PCH nicht findet. Lösung: WIN32 in die Liste der Includeverzeichnisse aufnehmen, oder die Includes wie oben umstellen.
    Gruß
    hal2000
    Erstmal glaube ich, dass dein Tag falsch ist, denn ich bin mir ziemlich sicher, dass es hier nicht um C++/CLI handelt.

    Und dann denke ich ist dein Ziel das ganze in einer .Net Sprache wie C# oder VB.Net umzusetzen?

    Dann mach doch nicht noch eine zusätzliche Library dazwischen, sondern nehm einfach direkt denen ihre Shared-Library, scheint ja ohne Probleme zu gehen, sogar Plattformunabhängig:
    github.com/hcrest/libfreespace

    Und dann holst du dir direkt die Funktionen wie freespace_init, oder freespace_openDevice etc.
    Entweder mittels DllImport(braucht eine DllMap für Mono, falls du die Plattformunabhängigkeit brauchst). Wenn du dann die Möglichkeit von 32 und 64 bit anwendungen anbieten willst, aber alles in einer AnyCPU Library, dann brauchst du so oder so LoadLibrary aus der WinAPI um dynamisch die entsprechende DLL zu laden, da das .Net Framework keine DllMap unterstützung hat.

    Dann wäre es vlt. sogar sinnvoll direkt mittels LoadLibrary und GetWindowProc zu arbeiten anstelle von DllImport, für *nix dann natürlich mittels dlopen und dlsym als jeweiliges equivalent, kann man sich relativ einfach als Helperfunktionen aufbauen, die dann zur Laufzeit jenach Betriebssystem gewählt werden.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Vielen Dank @hal2000 und @jvbsl für eure Hilfe.

    @hal2000 wie stellt man den Link zwischen dem Projekt und der Bib her?
    Habe unter Projekteigenschaften->Linker->Generell bei (AdditionalLibraryDirectories)

    @jvbsl ich habe libfreespace herrunter geladen und die lib. gebaut. Du meinst man kann die lib datei importieren und dann in einer vb Klasse die benötigten Funktion einfach über

    VB.NET-Quellcode

    1. <DllImport("libfreespace.lib")>
    2. Public Shared Sub TestFunction()
    3. End Sub

    definieren?

    So das geht leider nicht, wie kann man den die lib-Datei in das vb Programm reinlinken?

    Nachtrag
    Also ich habe ein MFC-Projekt angelegt, damit ich eine dll bekomme, also so wie vorher.
    Allerdings bin ich auf den Vorschlag von jvbsl eingegangen und habe lediglich einige Header durch include eingebunden, also im Prinzip den Anfang gelassen und die Testfunction() alles auskommentiert.
    In der Dokumentation von libfreespace steht zum Beispiel das die Funktion freespace_init() im Header-File freespace.h definiert ist. Daher dachte ich, dass ich alle Header deren Funktionen ich brauche einfach einbinde.
    Dann aus dem ganzen Spaß eine dll mache und diese dll einfach in eine vb Klasse importiere, sodass ich die ganzen Funktionen einfach über Klasse.function() nutzen kann.
    Problem ist jetzt, dass beim Starten meiner Windows-Forms Anwendung sich das ganze Programm(Form) aufhängt. Dabei habe ich nur eine einfache if-Abfrage genommen:

    VB.NET-Quellcode

    1. If Sensor.freespace_init() = 0 Then
    2. MsgBox("Es hat geklappt!!")
    3. End If
    Dateien
    • lib.zip

      (102,53 kB, 185 mal heruntergeladen, zuletzt: )

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

    Du sollst nicht die lib-datei verwenden. .lib ist bloß ein komisches Dateiformat von Visual Studio(wird sonst nirgends verwendet) um Symbole für DLLs zu speichern um das linken mit mangled names zu erledigen.

    du willst aber direkt die dll datei verwenden, nicht die lib-datei, da brauchst du dann auch nicht deine eigene Library zu builden. Die lib-Datei die du hast könnte auch(was auch wahrscheinlich ist) die statische Library sein, du willst aber die Shared/Dynamische Library.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @chris_2091 Hast Du dieses Tut Austausch von Daten zwischen einer VB.NET-exe und einer C-DLL, 32 und 64 Bit mal durchexerziert?
    Hast Du Dir das DLL-Projekt mal genau angesehen?
    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!
    Um deine "intermediate"-DLL wie anfangs gewünscht zu erstellen, brauchst du die Datei libfreespace.lib. Binde sie im C++-Projekt unter Linker --> Eingabe --> zusätzliche Abhängigkeiten ein (einfach libfreespace.lib eintragen) und gib das entsprechende Verzeichnis bei Linker --> Allgemein --> zusätzliche Bibliotheksverzeichnisse an.

    Tatsächlich ist es sinnvoller, der gesamten Code der Zwischen-DLL (hier: den Inhalt von TestFunction) direkt in VB.NET zu schreiben ( @jvbsl ). Dafür erstellst du dir die libfreespace.dll und bindest deren Exports per <DllImport()> ein. Ich habe das mal durchexerziert - das Problem liegt woanders. CMake setzt den Typ der Bibliothek auf "STATIC", d.h. er erstellt eine lib-Datei. Für die Verwendung aus C/C++ heraus ist das super, für VB.NET und <DllImport()> brauchst du aber eine DLL.

    Da du die lib-Datei schon hast, hast du auch eine VisualStudio-Projektmappe, die dir CMake erzeugt hat. Außerdem müssten alle Pfade zum DDK bei dir passen, sonst wäre CMake gescheitert. Stelle die Gesamtkonfiguration zunächst auf Release statt Debug. In den Eigenschaften des Projekts "libfreespace" änderst du nun folgendes:
    Allgemein --> Konfigurationstyp in DLL
    Allgemein --> Zielerweiterung in .dll
    C++ --> Präprozessor --> Bearbeiten und LIBFREESPACE_EXPORTS anfügen
    Linker --> Eingabe --> zusätzliche Abhängigkeiten: Hid.lib, Cfgmgr32.lib, setupapi.lib
    In allen C-Dateien ggf. #include <api/hidsdi.h> anpassen. Bei mir musste es #include <shared/hidsdi.h> heißen.

    Danach: Projekt "libfreespace" neu erstellen - das müsste durchlaufen und eine Datei libfreespace.dll produzieren. Diese kannst du in VB.NET so verwenden:

    VB.NET-Quellcode

    1. <DllImport("libfreespace.dll")>
    2. Public Shared Function freespace_init() As Int32
    3. End Function

    Blöderweise musst du in VB auch alle verwendeten Strukturen neu deklarieren - das kann mühsam sein und wiederum den Einsatz der Zwischen-DLL rechtfertigen. Im Anhang findest du die fertige DLL als Release, x86-Version und gelinkt gegen das DDK für Windows 8.1. Schau mal mit dem Dependency Walker in die DLL rein.
    Dateien
    Gruß
    hal2000

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

    Vielen Dank für eure Antworten!! Hoffe, dass ich mit meiner Studienarbeit jetzt weiter komme.

    @RodFromGermany ja ich habe dein Tut ausprobiert und halbwegs verstanden..hoffe ich ;)

    das Problem bei mir ist ja, dass ich keine dll mit allem drum und dran selber schreiben muss sondern alles eigentlich schon da ist, "nur" muss man's irgendwie integrieren.

    @hal2000 super Anleitung, ich probiere das gleich morgen früh aus.
    Diese Lib-Dateien Hid.lib, Cfgmgr32.lib, setupapi.lib sind die schon im Betriebssystem vorhanden?
    wo kann man
    C++ --> Präprozessor --> Bearbeiten und LIBFREESPACE_EXPORTS anfügen

    Ich habe dazu ein Bild im Anhang hochgeladen.

    Den Rest habe ich wie beschrieben durchgeführt, wobei es ein Projekt names ALL_BUILD gibt, das man eigentlich nutzt um die Bib zu bauen, habe dort und in dem Freespace-Projekt die beschriebenen Eigenschaften geändert.
    Wobei man nur in Freespace überhaupt die Option mit C/C++ erscheint.

    Beim Starten kommen zahlreiche Link und Syntax-Fehler ?! aus hidpi.h
    Bilder
    • Screenshot_freespace.jpg

      125,08 kB, 1.418×886, 179 mal angesehen
    Zu deinem Bild: Ja, genau dort. Im DropDown-Menü auf "Bearbeiten" und LIBFREESPACE_EXPORTS unten an die Liste anfügen. Einfach als "Wort" in eine neue Zeile, so wie es hier steht:



    Bitte die Eigenschaften nur im freespace-Projekt ändern. Das AllBuild-Projekt bindet das freespace-Projekt als Abhängigkeit ein, muss aber ein "Hilfsprogramm" bleiben. Ansonsten versucht er eine DLL für AllBuild zu erzeugen, was mangels Quellcode bzw. DllMain nicht funktionieren kann. Fang am besten nochmal komplett neu bei CMake an ("Delete Cache" und dann "Configure" / "Generate"), damit du ein sauberes Projekt hast.

    Link- und Syntaxfehler gibt es nicht gleichzeitig. Wenn es Syntaxfehler gibt, scheitert das Kompilieren. Dann ist ein Include-Pfad falsch oder er findet eine Headerdatei nicht. Die Fehlerquelle steht in der Spalte "Datei" im Fehlerfenster. Linkerfehler treten frühestens dann auf, wenn das Kompilieren fehlerfrei abgeschlossen ist. Du erkennst sie an der Angabe "LINK" im Fehlerfenster. In diesem Fall fehlt oft eine Abhängigkeit (Lib-Datei nicht eingetragen). Ach ja: Falls das nicht klar ist: Die Lib-Dateien müssen in der Liste natürlich untereinander stehen (und nicht mit Kommata wie oben), wie die Präprozessordefinitionen auch:

    Gruß
    hal2000

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

    also habe es jetzt mehrmals versucht es klappt einfach nicht. Ich kriege über 500 Syntaxfehler. Zum Beispiel:

    Error C2061 syntax error: identifier 'UsagePage' freespace c:\winddk\7600.16385.1\inc\api\hidpi.h 55
    Error C2059 syntax error: ';' freespace c:\winddk\7600.16385.1\inc\api\hidusage.h 26

    die Fehler enstehen alle in der Datei freespace_util.c

    Wenn man in CMake bei LIBFREESPACE_LIB_TYPE SHARED hinschreibt muss man nicht die ganzen Projekt-Einstellungen ändern.
    Allerdings kommen die gleichen Fehler :(

    das man die Strukturen alle neu definieren muss, gefällt mir nicht, das ist wirklich viel Aufwand.
    Mal ganz davon abgesehen, ob alle Datentypen in Visual Basic so verfügbar sind.
    In der Doku steht was von uint8_t oder int8_t .

    Daher habe ich weiter an der c-Klasse weiter gearbeitet, in der ich die lib und die ganzen header-files eingebunden habe.
    Um daraus eine dll zu machen, die ich dann nach vb importieren kann. Oder müsste man hier auch die ganzen Strukturen neu definieren?

    Beim Releasen der dll kommt die Warnung das Visual Studio die dll nicht starten konnte, aber ich denke das ist normal oder?
    Beim Importieren der dll in mein vb-net programm hatte ich hingegen Probleme. Wenn man es als die dll als neue Reference hinzufügt kommt folgende Fehlermeldung: A reference to ".dll" could not be added. Please make sure that the file is accessible and that it is a valid assembly or COM component.

    Außerdem habe ich die dll von mir und die dll von @hal2000 zu den Ressourcen hin zugefügt, aber das System wirft eine Exepection das die dll nicht gefunden werden.

    An unhandled exception of type 'System.DllNotFoundException' occurred in Cursorsteuerung.exe
    Additional information: Die DLL "libfreespace.dll": Das angegebene Modul wurde nicht gefunden. (Ausnahme von HRESULT: 0x8007007E) kann nicht geladen werden.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „chris_2091“ ()

    chris_2091 schrieb:

    über 500 Syntaxfehler

    Das liegt oft nicht am Code, sondern an irgendeinem Include, den er nicht findet. Manchmal ist auch nur die Reihenfolge falsch, wie schon am Anfang festgestellt. Schau mal durch alle Dateien durch und suche rot unterkringelte #includes. Überprüfe auch deinen Include-Path.

    chris_2091 schrieb:

    Wenn man in CMake bei LIBFREESPACE_LIB_TYPE SHARED hinschreibt muss man nicht die ganzen Projekt-Einstellungen ändern.

    Stimmt - habe ich mal gemacht, läuft auch durch. Das Problem daran ist aber, dass er dabei die Export-Präprozessordefinition falsch setzt - CMake setzt freespace_EXPORTS, richtig wäre LIBFREESPACE_EXPORTS. Der Rest stimmt aber.

    chris_2091 schrieb:

    Mal ganz davon abgesehen, ob alle Datentypen in Visual Basic so verfügbar sind.

    Sind sie - man muss nur nachschauen, wie sie im C-Projekt deklariert sind. Irgendwann kommt man z.B. bei uint8_t nach endlich vielen typedefs bei unsigned char raus, was in VB einfach Byte wäre. Pflichtlektüre für Interop: msdn.microsoft.com/en-us/library/26thfadc(v=vs.100).aspx, msdn.microsoft.com/en-us/library/fzhhdwae(v=vs.100).aspx und msdn.microsoft.com/en-us/library/ac7ay120(v=vs.100).aspx

    chris_2091 schrieb:

    Oder müsste man hier auch die ganzen Strukturen neu definieren?

    Das kommt darauf an, welche Strukturen die exportierten Funktionen nach außen verfügbar machen. Prinzipiell musst du alles neu deklarieren, was du in VB benutzt, sei es Funktion oder Parameter(-typ). Wenn du irgendwelche Strukturparameter einer Funktion nicht benutzt, genügt auch irgendwas exakt gleich großes bei Wertübergabe oder ein IntPtr bei Zeigern.

    chris_2091 schrieb:

    das System wirft eine Exepection das die dll nicht gefunden werden

    Das ist klar - die Ressourcen haben damit nichts zutun. Kopiere die DLL einfach in dasselbe Verzeichnis wie die exe, bei dir also in Debug/Release, wo auch Cursorsteuerung.exe liegt/erstellt wird. Überprüfe außerdem deine erstellte DLL mit dem Programm "Dependency Walker" vor der Verwendung - wenn die DLL nichts exportiert, kann VB auch nichts finden. Hier ist alles ok:


    Gruß
    hal2000

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

    bei mir funktionieren jetzt die ganz einfachen Funktionen wie freespace_init usw. Allerdings habe ich Probleme sobald man mehrere Inputs übergeben muss. zum Beispiel bei der Funktion

    LIBFREESPACE_API int freespace_getDeviceList (FreespaceDeviceId * list, int listSize, int * listSizeOut )
    -Get the list of attached devices.
    -Parameters: - list where to store the list of inserted devices
    - listSize the max number of ids that the list can hold
    - listSizeOutthe number of ids returned in the list
    Returns FREESPACE_SUCCESS=0 if no errors

    die Struktur FreespaceDeviceId ist als typedef int FreespaceDeviceId definiert ->Handle to a Freespace device.

    dazu habe ich das folgende in die Importklasse geschrieben:

    VB.NET-Quellcode

    1. <DllImport("libfreespace.dll")>
    2. Public Shared Function freespace_getDeviceList(ByVal FreespaceDeviceId As IntPtr, ByVal listSize As Int32, ByVal listSizeOut As IntPtr) As Int32
    3. End Function


    und dann im Hauptprogramm folgendes:

    VB.NET-Quellcode

    1. Private Sensor_device_id As Integer
    2. Private numIds As Integer
    3. 'Liste der erkannten Geräte
    4. Dim ip1 As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Sensor_device_id)) ' Setzen der jeweiligen Zeiger
    5. Dim ip2 As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(numIds))
    6. rc = Sensor.freespace_getDeviceList(ip1, 1, ip2)' 1 da ich sowieso nur ein Gerät abschließe im Beispiel des Herstellers ist es genauso
    7. Marshal.FreeHGlobal(ip1) ' Zeiger freigeben
    8. Marshal.FreeHGlobal(ip2)
    9. 'Prüfen ob ein Gerät gefunden wurde
    10. If rc = 0 Then
    11. MsgBox("Der Sensor wurde erkannt", MsgBoxStyle.Information, "Verbindung zum Sensor")
    12. Else
    13. MsgBox("Der Sensor wurde leider nicht erkannt", MsgBoxStyle.Critical, "Keine Verbindung zum Sensor")
    14. End If

    als Fehler wird mir angezeigt Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in '~.exe'.
    Überprüfen Sie, ob die Aufrufkonvention und die Parameter der PInvoke-Signatur mit der nicht verwalteten Zielsignatur übereinstimmen.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „chris_2091“ ()

    VB.NET-Quellcode

    1. <DllImport("libfreespace.dll",CallingConvention=...)>
    2. Public Shared Function freespace_getDeviceList(ByVal FreespaceDeviceId As IntPtr, ByVal listSize As Int32, ByRef listSizeOut As Int32) As Int32
    3. End Function

    Wichtig dürfte dabei trotzallem noch die CallingConvention sein, die du evtl. festlegen musst.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Die CallingConvention der Library ist cdecl, Standardeinstellung von DllImport ist aber stdcall. Das muss geändert werden - danke @jvbsl für den Hinweis.

    Mit der neuen Signatur ist der Aufruf dann:

    VB.NET-Quellcode

    1. Private numIds As Integer
    2. Dim pList As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Sensor_device_id)) ' Setzen der jeweiligen Zeiger
    3. rc = Sensor.freespace_getDeviceList(pList, 1, numIds)
    4. Marshal.FreeHGlobal(pList)


    Wenn FreespaceDeviceId sowieso nur ein int ist, fällt dessen Deklaration schonmal weg. Die Größe des anzulegenden Speichers ist dann IntPtr.Size (mal Anzahl der items, bei dir 1).
    Gruß
    hal2000

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