C++-Strukturen in VB-Typen konvertieren
von Sebastian Klose
Inhalt
Diese Ausgabe der Kolumne widmet sich wieder einem häufig in unserem Forum angesprochenen Thema, nämlich der API-Programmierung. Bei der Verwendung von API-Funktionen müssen häufig eigene Typen deklariert werden, die von den Funktionen benötigt werden. Bei den Funktionen des Windows-API sind die Deklarationen und die dazugehörigen Typdefinitionen meist bekannt. Einerseits kann man die C-Versionen im SDK nachlesen, andererseits gibt es zu diesem Zweck einige interessante Web-Seiten, auf denen die Deklarationen sowie die dazugehörigen Konstanten und Typen angegeben werden.
Will man nun eine API-Funktion aus dem Windows-API in seiner Anwendung benutzen, so kann man auf die Arbeit anderer zurückgreifen und die erforderlichen Deklarationen mit "Copy and Paste" in die eigenen Quellcodedateien einfügen.
Es gibt allerdings auch einige DLLs, bei denen die Funktionen und die von ihnen verwendeten Typen nicht bekannt sind. Dies ist bei einigen Windows-DLLs, aber vor Allem bei DLLs anderer Hersteller oft der Fall. In vielen Fällen findet man dann Beispiele für die Verwendung der DLL in einem C-Programm, der VB-Programmierer mit einem geringen Wissensstand auf dem Bereich der Programmiersprache C oder C++ wird jedoch seine Probleme haben, den Code nach VB zu konvertieren.
Vor einiger Zeit gab es auf einer deutschen Internetseite mit dem Namen vbSource.de ein Tool, das einem die Arbeit der Umwandlung von C-Deklarationen nach VB-Code abnehmen konnte. Leider gibt es diese Seite nicht mehr und das Tool ging für die Entwicklergemeinde verloren. Jedoch gibt es auf Planet-Source-Code.com ein entsprechendes Beispiel zu finden: C2VB.
Konvertieren von Typen aus C++ nach VB6
Wenn man eine unbekannte C++-API-Funktion oder eine unbekannte C++-Struktur hat, muss man manchmal selber die Konvertierung in Visual Basic Code in die Hand nehmen. Dafür muss man allerdings wissen wie: Im Prinzip ganz einfach, wenn man die folgende Tabelle hat:
C++-Typ | VB-Äquivalent |
---|---|
int | long |
long | Long |
short | Integer |
char | Byte |
char* | String |
char[NUM_OF_CHARS] | String * NUM_OF_CHARS |
float | Single |
double | Double |
Tabelle 1 : Konvertieren von C++-Standardtypen
C++-Typ | VB-Äquivalent |
---|---|
BYTE | Byte |
WORD | Integer |
DWORD | Long |
HANDLE | Long |
HWND | Long |
HDC | Long |
HBITMAP | Long |
HBRUSH | Long |
HCURSOR, HICON | Long |
HFILE | Long |
HFONT | Long |
HGDIOBJ | Long |
HGLOBAL | Long |
HINSTANCE | Long |
HMENU | Long |
LPTSTR | String |
BSTR | String |
LPCTSTR | String |
LPSTR | String |
Tabelle 2 : Konvertieren von Erweiterten C++-Typen
Sonderfälle
Boolsche Variablen
Der C++-Typ bool bzw. BOOL muss als Long in Visual Basic deklariert werden, da VB und C++ verschiedene numerische Werte zur Darstellung von True und False benutzen. Um in VB einer C++-Struktur den Wert True zu übergeben, muss der entsprechende Long-Wert auf 1 gesetzt werden (nicht wie in VB üblich auf -1). False entspricht (genau wie in VB) dem Wert 0.
Zeiger
Alle Zeigertypen (also datenTyp *varName oder erweiterte C++-Typen mit den Anfangsbuchstaben "LP" (für long pointer)) werden mit dem Long-Datentyp in Visual Basic implementiert (Ausnahme ist char*). Der Visual Basic Variable muss dann mit der VarPtr-Funktion die Speicheradresse der zuzuweisenden VB-Variablen zugewiesen werden.
Arrays
C++-Arrays werden zwar in VB auch als Arrays implementiert, jedoch ist dabei zu beachten, dass die Arraygrenze um 1 dekrementiert wird, denn in C++ bedeutet int myint[5] ein Array mit 5 Elementen (Indizes 0-4); in VB hingegeben bedeutet Dim lngArray(5) As Long ein Array mit 6 Elementen (Indizes 0-5).
Beispiele
typedef struct _devicemode { BCHAR dmDeviceName[CCHDEVICENAME]; WORD dmSpecVersion; WORD dmDriverVersion; WORD dmSize; WORD dmDriverExtra; DWORD dmFields; short dmOrientation; short dmPaperSize; short dmPaperLength; short dmPaperWidth; short dmScale; short dmCopies; short dmDefaultSource; short dmPrintQuality; short dmColor; short dmDuplex; short dmYResolution; short dmTTOption; short dmCollate; BCHAR dmFormName[CCHFORMNAME]; WORD dmLogPixels; DWORD dmBitsPerPel; DWORD dmPelsWidth; DWORD dmPelsHeight; DWORD dmDisplayFlags; DWORD dmDisplayFrequency; } DEVMODE;
Listing 1: C++-Strukturdefinition
... wird zu...
Private Type DEVMODE dmDeviceName As String * CCHDEVICENAME dmSpecVersion As Integer dmDriverVersion As Integer dmSize As Integer dmDriverExtra As Integer dmFields As Long dmOrientation As Integer dmPaperSize As Integer dmPaperLength As Integer dmPaperWidth As Integer dmScale As Integer dmCopies As Integer dmDefaultSource As Integer dmPrintQuality As Integer dmColor As Integer dmDuplex As Integer dmYResolution As Integer dmTTOption As Integer dmCollate As Integer dmFormName As String * CCHFORMNAME dmUnusedPadding As Integer dmBitsPerPel As Integer dmPelsWidth As Long dmPelsHeight As Long dmDisplayFlags As Long dmDisplayFrequency As Long End Type
Listing 2: Die vorige Struktur in VB
typedef struct tagCREATESTRUCT { LPVOID lpCreateParams; HINSTANCE hInstance; HMENU hMenu; HWND hwndParent; int cy; int cx; int y; int x; LONG style; LPCTSTR lpszName; LPCTSTR lpszClass; DWORD dwExStyle; } CREATESTRUCT;
Listing 3: C++-Strukturdefinition
... wird zu...
Private Type CREATESTRUCT lpCreateParams As Long hInstance As Long hMenu As Long hWndParent As Long cy As Long cx As Long y As Long x As Long style As Long lpszName As String lpszClass As String dwExStyle As Long End Type
Listing 4: Die vorige Struktur in VB
typedef struct _RECT { LONG left; LONG top; LONG right; LONG bottom; } RECT;
Listing 5: C++-Strukturdefinition
... wird zu...
Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type
Listing 6: Die vorige Struktur in VB
Zusammenfassung
Dieser kurze Artikel soll das Grundwerkzeug auf den Weg mitgeben, das man braucht, um Deklarationen übersetzen zu können. Ein weiterer interessanter Artikel zu diesem Thema von Ben Baird in englischer Sprache ist unter How to read C++ zu finden.
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.
Archivierte Nutzerkommentare
Klicken Sie diesen Text an, wenn Sie die 7 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.
Kommentar von Helmut Friedrich am 23.02.2011 um 06:50
Das hat mir weitergeholfen
Kommentar von Ulrich Schmid am 23.03.2007 um 14:02
In Visual Basic werden die variablen im speicher grundsätzlich in der reihenfolge angelegt in der sie in der type definition deklariert werden
--------------- ACHTUNG ACHTUNG ---------------
Man kann aber leider nicht darauf vertrauen das zwischen den einzelnen Variablen keine weiteren bytes eingefügt werden. Der Visual Basic Compiler fügt einzelne bytes zwischen die variablen um auf gerade 32 Bit Addressen zugreifen zu können.
Man kann das mit copymemory und varptr leicht feststellen:
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, source As Any, ByVal Bytes As Long)
Private Type OPERATION_MESSAGE
eOpType As Byte
eOperation As Integer
bIsAvail As Integer
dwTarget As Long
dwValue As Long
lwmin As Long
lwMax As Long
lwInc As Long
End Type
Dim Bytes(24) As Byte
Dim opmsg As OPERATION_MESSAGE
Dim i
Dim strBytes As String
Private Sub Form_Load()
With opmsg
.eOpType = &HEE
.eOperation = &HF1F2
.bIsAvail = &HE1E2
.dwTarget = &HD1D2D3D4
.dwValue = &HC1C2C3C4
.lwmin = &HB1B2B3B4
.lwMax = &HA1A2A3A4
.lwInc = &H1020304
End With
CopyMemory Bytes(0), opmsg, Len(opmsg)
For i = 0 To UBound(Bytes)
strBytes = strBytes & Right("00" & Hex(Bytes(i)), 2)
Next i
Debug.Print strBytes
Debug.Print Hex(VarPtr(opmsg))
Debug.Print Hex(VarPtr(opmsg.eOpType))
Debug.Print Hex(VarPtr(opmsg.eOperation))
Debug.Print Hex(VarPtr(opmsg.bIsAvail))
Debug.Print Hex(VarPtr(opmsg.dwTarget))
Debug.Print Hex(VarPtr(opmsg.lwmin))
Debug.Print Hex(VarPtr(opmsg.lwMax))
Debug.Print Hex(VarPtr(opmsg.lwInc))
End Sub
Im Debug Fenster erscheint der string
EE00F2F1E2E10000D4D3D2D1C4C3C2C1B4B3B2B1A4A3A2A104
un nicht wie erwartet
EEF2F1E2E1D4D3D2D1C4C3C2C1B4B3B2B1A4A3A2A104030201
Nachfolgen erscheinen die Adressen der einzelnen variablen
Kommentar von am 24.09.2005 um 02:20
Thanks for making us aware of the broken link. It should be fixed by now.
Kommentar von am 04.08.2005 um 13:03
How to read C++:
http://www.vbthunder.com/articles/readcpp.php
and not .asp
Kommentar von Daniel am 09.07.2005 um 19:25
Wie würde dieser API-Call in VB6 aussehen?
Ich kenne nur den C++ Code einer DLL und will nun diese Funktion aus VB heraus aufrufen:
ISC_STATUS isc_attach_database(
ISC_STATUS *status_vector,
short db_name_length,
char *db_name,
isc_db_handle *db_handle,
short parm_buffer_length,
char *parm_buffer);
Also:
Public declare Funcion isc_attach_database lib "..." (...)
Zu ISC_STATUS kann ich nur das schreiben:
status_vector-->ISC_STATUS *
Pointer to the error status vector
ISC_STATUS:
Status information is reported in an error status vector, declared in applications as an array of
twenty long integers, using the following syntax:
typedef long ISC_STATUS;
ISC_STATUS status_vector[20];
Ich freue mich auf jeden Lösungsansatz, danke.
Kommentar von Oliver am 27.04.2005 um 10:28
Hallo Karim,
in C++ ist das recht einfach:
char MyString[0x100]
int i = 42;
sprintf(MyString, "%d", i);
Durch die Verwendung für sprintf kannst du noch eine ganze Reihe von Formatierungen durchführen. Möchtest du die Zahl z. B. Hexadezimal ausgeben lassen sieht das so aus:
sprintf(MyString, "0x%08x", i);
Damit erhälst du dann folgende Ausgabe: 0x0000002A
Was allerdings sichergestellt sein muss, ist das der String auch in das Array reinpasst, sonst fängst du dir einen Pufferüberlauf ein.
Weitere Infos zum Thema Stringformatierung findest du hier:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_format_specification_fields_.2d_.printf_and_wprintf_functions.asp
Gruss,
Oliver
Kommentar von karim am 13.04.2005 um 13:08
hallo,
ich habe eine kleine Frage in C++.
ich möchte wissen,wie mann von integer zu string konvertieren kann!
in java kann man Zm int x=5; string S=""+x;konvertieren.
von Der Umwandlung in C++ habe ich keine Ahnung.
ich dake ihnen im voraus.