![]() |
DLL - Probs mit Strings
Moin zusammen !
Ich habe hier eine DLL, um DVB-Geräte abzufragen/zu steuern (von TechnoTrend, ttBdaDrvApi_Dll.dll). Zu dieser DLL habe ich eine Source in C zur 'Ansprache'. Die DLL lade ich dynamisch, was auch so weit mit den meisten Funktionen einwandfrei klappt. Allerdings gibt es eine Func zum Auslesen von Gerätenamen/-Typen, mit der ich nicht klar komme - d.h. in den zurückgelieferten Strings eines Records lese ich nur 'dummes Zeug'. Das Funktions-Ergebnis ist ok, ich habe auch keine Fehler. Deklarationen in C:
Code:
In Delphi hab ich das so umgesetzt:
// Lists all possible frontend types.
typedef enum { /// not set TYPE_FE_UNKNOWN = 0, /// DVB-C TYPE_FE_DVB_C, /// DVB-S TYPE_FE_DVB_S, /// DVB-S2 TYPE_FE_DVB_S2, /// DVB-T TYPE_FE_DVB_T, /// ATSC TYPE_FE_ATSC, /// DSS TYPE_FE_DSS, /// DVB-C and DVB-T TYPE_FE_DVB_CT, /// TT-premium with Dual DVB-S2 and digital capture TYPE_FE_DVB_S2_PREM } TYPE_FRONT_END; ... /// Lists the bda filternames. typedef struct { char szTunerFilterName[MAX_PATH]; char szTunerFilterName2[MAX_PATH]; char szCaptureFilterName[MAX_PATH]; char szAnlgTunerFilterName[MAX_PATH]; char szAnlgCaptureFilterName[MAX_PATH]; char szSTBCaptureFilterName[MAX_PATH]; char szProductName[MAX_PATH]; TYPE_FRONT_END FeType; } TS_FilterNames, *pTS_FilterNames; ... // functions to get something from the driver ... TTBDADRVAPI TYPE_RET_VAL bdaapiGetDevNameAndFEType(HANDLE hOpen, pTS_FilterNames FilterNames); ...
Code:
Was mache ich hier falsch ?
...
type PTT_FilterNames = ^TT_FilterNames; TT_FilterNames = record //packed record TunerFilterName : array[0..MAX_PATH] of char; TunerFilterName2 : array[0..MAX_PATH] of char; CaptureFilterName : array[0..MAX_PATH] of char; AnlgTunerFilterName : array[0..MAX_PATH] of char; AnlgCaptureFilterName : array[0..MAX_PATH] of char; STBCaptureFilterName : array[0..MAX_PATH] of char; ProductName : array[0..MAX_PATH] of char; FeType : word; end; ... // als var in einer Klasse: _bdaapiGetDevNameAndFEType : function(TThwnd : HWND; var FilterNames : TT_FilterNames) : HRESULT; cdecl; ... // Laden: @_bdaapiGetDevNameAndFEType := GetProcAddress(LibHdl, 'bdaapiGetDevNameAndFEType'); ... // Funktion ausführen if (_bdaapiGetDevNameAndFEType(Dev.DevHdl, Dev.FilterNames) = 0) then begin Log('--> TunerFilter: ' + strpas(Dev.FilterNames.TunerFilterName)); Log('--> TunerFilter2: ' + strpas(Dev.FilterNames.TunerFilterName)); Log('--> CaptureFilter: : ' + strpas(Dev.FilterNames.CaptureFilterName)); Log('--> AnlgTunerFilter: : ' + strPas(Dev.FilterNames.AnlgTunerFilterName)); Log('--> AnlgCaptureFilter: : ' + strPas(Dev.FilterNames.AnlgCaptureFilterName)); Log('--> STBCaptureFilterName: : ' + strPas(Dev.FilterNames.STBCaptureFilterName)); Log('--> ProductName: : ' + strPas(Dev.FilterNames.ProductName)); case Dev.FilterNames.FeType of 0: s := 'not set'; 1: s := 'DVB-C'; 2: s := 'DVB-S'; 3: s := 'DVB-S2'; 4: s := 'DVB-T'; 5: s := 'ATSC'; 6: s := 'DSS'; 7: s := 'DVB_CT'; 8: s := 'DVB_S2_PREM'; else s := 'unknown'; end; Log('--> Front-End: ' + s); end; |
AW: DLL - Probs mit Strings
Kann es sein, dass Deine Char-Arrays um jeweils ein Char zu groß sind? IIRC gibt in C eine Zahlenagabe in eckigen Klammern die Größe an. Die Aufrufkonvention cdecl ist auch richtig? Und Du solltest besser das "packed" entkommentieren. Achja, auch nicht unwichtig: welche Delphi-Version setzt Du ein? Ggf. musst Du wohl aus Char Ansichar machen.
|
AW: DLL - Probs mit Strings
Alles mit Delphi 7 gemacht.
cdecl sollte ok sein - es gibt noch dutzend andere func's die ich so aufrufe und die funzen. Ob Packed Record oder nur Record macht anscheinen keinen Unterschied. Ich habe MAX_PATH 'einfach so' übernommen. Kann natürlich möglich sein, dass das in C/Delphi unterschiedlich deklariert ist. Ich habe MAX_PATH auch mal neu deklariert und zig verschiedene Werte eingesetzt - nada .... Auch wenn MAX_Path zu groß sein sollte, müsste ich doch wenigstens für den 1. Wert 'TunerFilter' irgendwas gescheites bekommen ?! AnsiChar statt Char bringt auch keine Änderung. Das dumme ist: Ich hatte das schon mal am laufen, allerdings ist mir der Source abhanden gekommen und das ist ein paar Jahre her .... |
AW: DLL - Probs mit Strings
*Pfuh* da stoßen meine bescheidenen Kenntnisse bereits an ihre Grenzen. Hast Du den Record vor dem Aufruf genullt? Ich weiß ja nicht, ob die DLL das intern erledigt, schaden kann es wohl nicht.
|
AW: DLL - Probs mit Strings
Nein, hab ich nicht. Warum auch ?
Vermute eher mal, das die REC-Deklaration falsch ist und / oder das casten nicht funktioniert.... |
AW: DLL - Probs mit Strings
Dennoch solltest du es mal mit stdcall versuchen.
Vom Aufruf her sind die sich gleich. Nur das Aufräumen der Parameter ist anders.
Delphi-Quellcode:
Das PACKED hat auf die Char/AnsiChar-Arrays keine Wirkung, da diese sowieso nur aus einzelnen Bytes bestehen und dadurch praktisch nicht ausgerichtet werden.
type
{$MINENUMSIZE 2} TYPE_FRONT_END = ( TYPE_FE_UNKNOWN, // not set TYPE_FE_DVB_C, // DVB-C TYPE_FE_DVB_S, // DVB-S TYPE_FE_DVB_S2, // DVB-S2 TYPE_FE_DVB_T, // DVB-T TYPE_FE_ATSC, // ATSC TYPE_FE_DSS, // DSS TYPE_FE_DVB_CT, // DVB-C and DVB-T TYPE_FE_DVB_S2_PREM); // TT-premium with Dual DVB-S2 and digital capture {$MINENUMSIZE 1} // Standardwert TS_FilterNames = {packed} record szTunerFilterName: array[0..MAX_PATH-1] of AnsiChar; // oder [1..MAX_PATH]; szTunerFilterName2: array[0..MAX_PATH-1] of AnsiChar; szCaptureFilterName: array[0..MAX_PATH-1] of AnsiChar; szAnlgTunerFilterName: array[0..MAX_PATH-1] of AnsiChar; szAnlgCaptureFilterName: array[0..MAX_PATH-1] of AnsiChar; szSTBCaptureFilterName: array[0..MAX_PATH-1] of AnsiChar; szProductName: array[0..MAX_PATH-1] of AnsiChar; FeType: TYPE_FRONT_END; end; function bdaapiGetDevNameAndFEType(hOpen: THandle; var FilterNames: TS_FilterNames): HRESULT; stdcall; (Sie werden an den Bytegrenzen ausgerichtet, was somit dem PACKED entspricht) Aber auf FeType dürfte PACKED eine wirkung zeigen, jedenfalls bei der falschen Arraylänge, da 7 Byte mehr (1 je Array), was auf vielfache von 2 (
Delphi-Quellcode:
), also 8 aufgerundet wird und somit diesen Wert verschiebt.
Sizeof(TYPE_FRONT_END)
Wie bist du eigentlich von HANDLE auf HWND gekommen? Ist das denn wirklich ein Fenster-Handle? |
AW: DLL - Probs mit Strings
KA, wieso ich da HWND (integer) statt THandle (LongWord) drin habe ....
Hab es geändert - funzt nach wie vor (alle anderen Funktionen). Hab noch mal mit MAX_PATH gespielt und in meinen alten Files doch noch was gefunden: Wenn ich 389 (was ne dösige Zahl !?) einsetze, kommt (teilweise) was brauchbares heraus. Leider kommt für FE-Type immer nur eine '0'. Interessant ist auch: Es gibt DLL-Versionen 1.0.1.11 und 1.0.1.21. Die .11er hat einen 'kürzeren' Record. Mit MAX_PATH = 389 kann ich dann auch die FE-Typen auslesen. |
AW: DLL - Probs mit Strings
Naja, MAX_PATH ist ja auch nur eine Konstante, wenn die intern geändert wird darf man sich nicht wundern. Aber wer kommt auf so eine bescheuerte Idee? Gibt es keine Doku dazu, wo das zumindest erwähnt wird?
|
AW: DLL - Probs mit Strings
0..389 = 390, da du wohl immernoch das -1 vergessen hast.
Das wären 1,5* ![]()
Delphi-Quellcode:
Und wenn man sich mit garnicht ssicher ist, dann doch eher wie Folgt.
var
S: TFileStream; N: FilterNames; S := TFileStream.Create('dateiname', fmCreate); FillChar(N, SizeOf(N), 0); bdaapiGetDevNameAndFEType(hOpen, N); S.WriteBuffer(N, SizeOf(N)); FillChar(N, SizeOf(N), 255); bdaapiGetDevNameAndFEType(hOpen, N); S.WriteBuffer(N, SizeOf(N)); S.Free;
Delphi-Quellcode:
Und die Datei hier anhängen.
function bdaapiGetDevNameAndFEType(hOpen: THandle; P: Pointer): HRESULT; stdcall;
var S: TFileStream; B: array[0..8191] of Byte; // 8 KB sollten groß genug sein (selbst 2 KB dürften, laut Spezifikation, ausreichen) S := TFileStream.Create('dateiname', fmCreate); FillChar(B, SizeOf(B), 0); bdaapiGetDevNameAndFEType(hOpen, @B); S.WriteBuffer(B, SizeOf(B)); FillChar(B, SizeOf(B), 255); bdaapiGetDevNameAndFEType(hOpen, @B); S.WriteBuffer(B, SizeOf(B)); S.Free; Ginge natürlich auch einfacher, wenn man die Möglichkeiten des Debuggers nutzen und sich die Variable direkt im Speicher ansieht. |
AW: DLL - Probs mit Strings
Liste der Anhänge anzeigen (Anzahl: 2)
Ich habs einfach mal so gemacht:
Code:
Man sieht die Strings in der Datei - Es sind 2 Geräte die gelistet werden.
S.WriteBuffer(Dev.FilterNames, SizeOf(Dev.FilterNames));
Hab mir das aber nur mit dem Editor angesehen. 'Dateiname1.txt' ist für die DLL .11, 'Dateiname2.txt' für die .21 Für den Debugger bin ich A) 'zu blöd' und B) habe ich den beim proggen mit DirectShow Dingen eh immer aus. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz