NancyG Geschrieben 22. Oktober 2012 Teilen Geschrieben 22. Oktober 2012 Hallo Leute, ich habe ein Problem, mit der Deklaration von Strukturen in VB - und der Dek. einer C-dll. Hier der Code aus der Header-Datei. typedef struct tagDM_VARKEYA { DWORD dwKeyType; DWORD dwID; char szName[ MAX_DM_VAR_NAME + 1 ]; LPVOID lpvUserData; } DM_VARKEYA, FAR *LPDM_VARKEYA; #if.... DM_VARKEY = DM_VARKEYA; ... ... In VB steht dann dieses hier: <StructLayout(LayoutKind.Sequential, Pack:=1)> Public Structure DM_VARKEY Public dwKeyType As UInt32 Public dwID As UInt32 Public szName() As Char Public lpvUserData As IntPtr End Structure Und hier habe ich schon das erste Problem: Wie kann ich den szName auf 128 Byte setzen. Ein Dim vKey as DM_VARKEY Marshal.SizeOf(vKey) sagt, dass die Struktur nur 12 Byte groß ist. 2 x DWORD (4 Byte) + 1 x IntPtr (4 Byte) = 12.. wo ist szName? Nun zur DLL. in der API_Doku steht dies hier: BOOL DMGetValue (LPDM_VARKEY lpdmVarKey, DWORD dwItems, LPDM_VAR_UPDATE_STRUCT lpdmvus, LPCMN_ERROR lpdmError); Unter C würde dies so aussehen. CMN_ERROR err; DM_VARKEY vKey; DM_VAR_UPDATE_STRUCT update; DWORD items = 1; ZeroMemory(&vKey, sizeof(vKey)); ZeroMemory(&err, sizeof(err)); vKey.dwKeyType = DM_VARKEY_NAME; //DM_VARKEY_NAME = 2 strcpy(varKey.szName,"TESTVAR"); varKey.lpvUserData = NULL; DMGetValue( &vKey, items, &update, &err ); //funktioniert super! Wie muss die Funktion nun aber in VB deklariert werden? Ich habe es so gemacht, nur leider funktioniert das nicht. Declare Ansi Function DM_GetValue Lib "dmclient.dll" Alias "DMGetValueA" _ (ByVal lpdmVarKey As IntPtr, _ ByRef dwItems As UInt32, _ ByVal lpdmvus As IntPtr, _ ByVal lpdmError As IntPtr) As Boolean Ich hoffe, das Ihr mir da helfen könnt. Steh völlig auf dem Schlauch. vG Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
raiserle Geschrieben 26. Oktober 2012 Teilen Geschrieben 26. Oktober 2012 Hi NancyG, ich habe ein Problem, mit der Deklaration von Strukturen in VB - und der Dek. einer C-dll. Hier der Code aus der Header-Datei. Das Zauberwort: Marshal. Wenn ich den Code so sehe - Siemens lässt grüßen! Was du machen willst ist: managed mit unmanaged code. Beim .Net ist es so, dass sich Net um den Speicher kümmert, alloziert, freigibt usw... Diese Mechanismen gilt es für diesen Anwendungsfall auszuschalten. Ein Stück davon hast du schon drin: <StructLayout(LayoutKind.Sequential, Pack:=1)> . typedef struct tagDM_VARKEYA { DWORD dwKeyType; DWORD dwID; char szName[ MAX_DM_VAR_NAME + 1 ]; LPVOID lpvUserData; } DM_VARKEYA, FAR *LPDM_VARKEYA; [/QUOTE] Sollte so funktionieren: [CODE] <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _ Public Class DM_VARKEY <MarshalAs(UnmanagedType.U4)> _ Public dwKeyType As DM_VARKEY_TYPE <MarshalAs(UnmanagedType.U4)> Public dwID As UInt32 <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=(MAX_DM_VAR_NAME + 1))> Public szName As [String] Public lpvUserData As IntPtr End Class Es fehlt noch die Err_Struct : <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> Public Class CMN_ERROR <MarshalAs(UnmanagedType.U4)> Public dwError1 As UInt32 Public dwError2 As UInt32 Public dwError3 As UInt32 Public dwError4 As UInt32 Public dwError5 As UInt32 <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=512)> Public szErrorText As [String] Sub reset() dwError1 = 0 dwError2 = 0 dwError3 = 0 dwError4 = 0 dwError5 = 0 szErrorText = "" End Sub End Class Mit [reset()] kannst du das Objekt schnell wieder leeren. Und hier die DLL: <DllImport("dmclient.dll", EntryPoint:="DMGetValueA", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Winapi)> _ Private Shared Function DMGetValue(<[In]()> <MarshalAs(UnmanagedType.LPStruct)> ByVal lpdmVarKey As DM_VARKEY, _ <[In]()> ByVal dwItems As UInt32, _ <[In]()> ByVal lpdmvus As IntPtr, _ <[In](), Out()> ByRef lpdmError As CMN_ERROR ) As Boolean Ich würde dir aber die DMGetValueWait empfehlen. Bei dieser werden die Daten, sofern sie keine Internen Variablen sind, aus der SPS gelesen/synchronisiert. Die (WAIT) erwartet aber eine CallBack-Funktion, die du über DELEGATE realisieren kannst. Du solltest darauf achten, dass du überall das gleiche CharSet benutzt. Ich empfehle CharSet.Ansi Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.