Die Community zu .NET und Classic VB.
Menü

C++-Strukturen in VB-Typen konvertieren

 von 

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.