INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.


Antwort schreiben 

LV 7.1, VC++-DLL (VC++2008), string-Übergabe



Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!

12.03.2010, 14:39
Beitrag #1

ptillmann Offline
LVF-Neueinsteiger


Beiträge: 1
Registriert seit: Mar 2010

7.1.1
-
de

34246
Deutschland
LV 7.1, VC++-DLL (VC++2008), string-Übergabe
Liebe LeserInnnen,

meine Aufgabe ist es, eine Wrapper-DLL für LV 7.1 zu erstellen. Mein Problem ist die Übergabe von Strings.

Die DLL (VC++ 2008) stellt folgende Funktion bereit:
<blockquote>extern "C" CZPLSDLL_API long WINAPI get_ComponentNames (LPCSTR sCalibFile,
long nExperiment, long nComponent, LPSTR sComponent, long *nComponentSize)
{
<blockquote>[...]
char nstring[100];
[...]

size_t origsize = strlen(nstring);
origsize = min(100,origsize);
memcpy(sComponent,nstring,origsize);
memcpy(sComponent+origsize,"",1);
*nComponentSize = origsize;

return 0;
</blockquote>
}
</blockquote>
Compiler-Einstellungen:
- __stdcall
- /clr (weil gewrappte DLL in C# geschrieben ist)
- /Zp1 (Ausrichten Strukturmember: 1 Byte)


Das Problem:
Wenn ich hinter char nstring[100]; nstring wie folgt deklariere
<blockquote> char nstring[100];
strcpy(nstring,"asdh");
</blockquote>
übernimmt LabVIEW den String korrekt. Wenn ich den String aus meiner gewrappten DLL fülle z.B.
<blockquote> char nstring[100];
String ^str = prd.getString(0);
pin_ptr<const wchar_t> wch = PtrToStringChars(str);
// Convert to a char*
const size_t newsize = 100;
WideCharToMultiByte(CP_ACP, 0, wch, -1, nstring, 100, NULL, NULL);
</blockquote>
(das Ganze liest einen String aus der gemanageden C#-DLL ein, kodiert ihn auf ASCII um und schreibt ihn nach nstring), dann zeigt LabVIEW nur Müll an.

Wenn ich die Wrapper-DLL aus einen VC++-Programm aus aufrufe, kann ich in beiden Varianten der String-Deklaration die Strings korrekt auslesen.

In beiden Varianten der String-Deklaration ist die Stringlänge korrekt, d.h.
<blockquote> sprintf(nstring,"Laenge %d", strlen(nstring));
</blockquote>
liefert die korrekten Werte an LabVIEW und mein VC++-Programm.

Ich habe das Gefühl, es könnte etwas mit UNICODE und ASCII zu tun haben. Nach Lesen des DLL-Tutorials und 3 Jahren Forums-Einträgen, sowie Stunden der alternativen Deklaration (std:string, Cstr, strcpy, memcpy, ...) erlaube ich mir die Frage hier zu stellen.

Ich habe z.Z. keinen Zugriff auf den LV-Code.


Danke

Peter Tillmann
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Anzeige
12.03.2010, 20:34
Beitrag #2

rolfk Offline
LVF-Guru
*****


Beiträge: 2.305
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
LV 7.1, VC++-DLL (VC++2008), string-Übergabe
Also in Deinem C code ist einiger Müll drin der wenig Sinn macht:

' schrieb:<blockquote>extern "C" CZPLSDLL_API long WINAPI get_ComponentNames (LPCSTR sCalibFile,
long nExperiment, long nComponent, LPSTR sComponent, long *nComponentSize)
{
[indent][...]
char nstring[100];
[...]

size_t origsize = strlen(nstring);
origsize = min(100,origsize);
Was soll das? nstring ist 100 bytes lang. Entweder ist der String in nstring sowieso kürzer als 100 (eigentlich 99 Bytes) oder die Funktion die da hineingeschrieben hat hat schon lange Speicher überschrieben den sie nicht hätte überschreiben sollen und dann macht diese Sicherheitsabfrage das auch nicht mehr gut.

Zudem liefert Dir die Funktion WideCharToMultiByte() die Du da ja gemäss dem späteren Code verwendest als Returnwert genau diese Zahl um eins vermindert und dann ist es dumm um da noch mal ein strlen() zu machen.

Zitat:memcpy(sComponent,nstring,origsize);
memcpy(sComponent+origsize,"",1);
Wo bitte schön ist das NULL Byte zum Abschluss des Stringes. LPZSTR ist ein Null-terminated ASCI String aber memcpy() macht keine NULL Bytes in einen String.

Zitat:Wenn ich den String aus meiner gewrappten DLL fülle z.B.
[indent] char nstring[100];
String ^str = prd.getString(0);
pin_ptr<const wchar_t> wch = PtrToStringChars(str);
// Convert to a char*
const size_t newsize = 100;
WideCharToMultiByte(CP_ACP, 0, wch, -1, nstring, 100, NULL, NULL);
</blockquote>
(das Ganze liest einen String aus der gemanageden C#-DLL ein, kodiert ihn auf ASCII um und schreibt ihn nach nstring), dann zeigt LabVIEW nur Müll an.

Wenn ich die Wrapper-DLL aus einen VC++-Programm aus aufrufe, kann ich in beiden Varianten der String-Deklaration die Strings korrekt auslesen.

In beiden Varianten der String-Deklaration ist die Stringlänge korrekt, d.h.
<blockquote> sprintf(nstring,"Laenge %d", strlen(nstring));
</blockquote>
liefert die korrekten Werte an LabVIEW und mein VC++-Programm.

Ich habe das Gefühl, es könnte etwas mit UNICODE und ASCII zu tun haben. Nach Lesen des DLL-Tutorials und 3 Jahren Forums-Einträgen, sowie Stunden der alternativen Deklaration (std:string, Cstr, strcpy, memcpy, ...) erlaube ich mir die Frage hier zu stellen.

Ich habe z.Z. keinen Zugriff auf den LV-Code.

Das ist schade, denn könnte es sein dass das LabVIEW Programm schlichtweg vergisst entsprechende Buffer für die Stringparameter anzulegen? LabVIEW macht zwar im Diagram überall automatische Memoryverwaltung und passt Buffer wann nötig an aber für die Call Library Node und C Datenpointer geht das schlichtweg nicht, da LabVIEW auf keine einzige Art zum voraus wissen kann wie gross ein Buffer sein muss, und die DLL diesen normalerweise nicht selber anlegt und wenn sie es auch täte kommt dieser Pointer nie durch die Parameterliste zum Aufrufer zurück.

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Antwort schreiben 


Möglicherweise verwandte Themen...
Themen Verfasser Antworten Views Letzter Beitrag
  DLL mit String Nullpointer Übergabe Hubert R. 5 6.002 25.08.2023 11:43
Letzter Beitrag: rolfk
  Übergabe eines struct arrays an eine DDL und wieder Auslesen SK-AC 4 7.244 12.08.2010 17:01
Letzter Beitrag: rolfk
  Mehrere Cuda DLLs Context-Übergabe grey 2 6.135 17.06.2010 19:50
Letzter Beitrag: rolfk
  Unhandled exception bei Übergabe eines CArrays abrissbirne 8 9.231 25.04.2008 23:31
Letzter Beitrag: abrissbirne
  Übergabe eines C Array abrissbirne 1 5.026 13.04.2008 22:12
Letzter Beitrag: rolfk
  Übergabe von Datenzeiger Cubaner 3 6.019 22.01.2008 13:18
Letzter Beitrag: rolfk

Gehe zu: