AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein UTF8 als WideString an ActiveX (LPCTSTR)
Thema durchsuchen
Ansicht
Themen-Optionen

UTF8 als WideString an ActiveX (LPCTSTR)

Ein Thema von taveuni · begonnen am 22. Mai 2012 · letzter Beitrag vom 23. Mai 2012
Antwort Antwort
taveuni

Registriert seit: 3. Apr 2007
Ort: Zürich
533 Beiträge
 
Delphi 11 Alexandria
 
#1

UTF8 als WideString an ActiveX (LPCTSTR)

  Alt 22. Mai 2012, 10:51
Hallo,
Ich bin am verzweifeln. Seit Tagen maile ich mit einer Entwicklerin ohne Ergebnis.
Diese pflegt ein ActiveX für deren Subsystem (geschrieben in C++). In diesem besteht seit Jahren eine Funktion
welche als Parameter einen Dateinamen enthält. Beim Import des ActiveX wird in der Typ Bibliothek seit Delphi6
(aktuell bin ich bei XE2) ein WideString definiert. Bisher war kein Problem auszumachen. Neu wird die Anlage
in China eingesetzt und es können auch chinesische Dateinamen übergeben werden.
Ich hoffte mit XE2 diesbezüglich ohne Modifikationen auszukommen.

Nun: Intern wird das ActiveX scheinbar ohne "define Unicode" kompiliert.
Deshalb ist der vom ActiveX erwartete Datentyp ein 8Bit LPCSTR.
http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
Also eigentlich ein Array of Char in UTF8 kodierung.

Soweit so gut - Die einzige Möglichkeit welche ich gesehen habe ist den Parameter so zu übergeben: UTF8Encode(DelphiUnicodeString).
Im Debugger des ActiveX sieht die Entwicklerin aber auch so nur ??? (siehe Screenshot)

Ist es auf der Basis überhaupt möglich das wir uns treffen?

Danke für jede Hilfe
Miniaturansicht angehängter Grafiken
debugger.jpg  
Die obige Aussage repräsentiert meine persönliche Meinung.
Diese erhebt keinen Anspruch auf Objektivität oder Richtigkeit.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#2

AW: UTF8 als WideString an ActiveX (LPCTSTR)

  Alt 22. Mai 2012, 13:00
Externe Schnittstellen verändern sich nicht, nur weil du jetzt einen anderen Compiler verwendest.

Sind diese als ANSI deklariert, dann bleiben sie ANSI.

Und wird intern z.B. die ANSI-WinAPI für Dateizugriffe verwendet, dann kann auch nur ANSI verwendet werden, da diese Schnittstellen kein UTF-8 vertehn.
Also ohne die verwendete Komponente intern nicht auf Unicode umzustellen, wirst du auch kein Unicode verwenden können.

Einzige Ausnahme sind Strings, welche nur intern verwendet werden und nirgendwo explizit als ANSI (aktuelle CodePage) vorliegen müssen,
wo man Diesem implizit heimlich einen UTF-8-kodierten Text unterschiebt.

Man kann teilweise die Codepage (des Threads, Prozesses oder gar vom ganzen Windows) umstellen, aber in wie weit das hilft, müßte man ausprobieren.



Alternativ kannst du beim ANSI bleiben und mußt nur dafür sorgen, daß die "langen" Datei- und Pfadnamen in das kurze 8.3-Dateiformat umgewandelt werden.
Das geht natürlich nur für existierende Dateien. (Speichern von Dateien würde ausschließlich als ANSI bleiben)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (22. Mai 2012 um 13:03 Uhr)
  Mit Zitat antworten Zitat
taveuni

Registriert seit: 3. Apr 2007
Ort: Zürich
533 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: UTF8 als WideString an ActiveX (LPCTSTR)

  Alt 22. Mai 2012, 13:17
Hmhh..

Noch mal für mein Verständnis:
Wenn ich diesem Parameter welchen mir Delphi beim Import als Widestring angelegt hat einen
"AnsiString" als Widestring mitgebe (also z.b. c:\MeineDatei.mov) kommt diese so an.
Wenn ich "MeineDatei" chinesisch mitgebe ( c:\我的档案.mov) kommt auf der anderen Seite c:\????.mov an.

Wenn ich das ActiveX in VisualStudio in C++ importiere ist der Parameter LPCSTR. Dieser ist ja 8Bit.
Ich kann dann dort z.b. für den Dateinamen: c:\下周我要去度假.mov
dies übergeben:
Code:
char tmp[] = {'c', ':', '\\', 0xE4, 0xB8, 0x8B, 0xE5, 0x91, 0xA8, 0xE6, 0x88, 0x91, 0xE8, 0xA6, 0x81, 0xE5, 0x8E, 0xBB, 0xE5, 0xBA, 0xA6, 0xE5, 0x81, 0x87, '.', 'm', 'o', 'v', 0x00 }
Also müsste ich doch aus Delphi auch einen UTF8 codierten (Ansi?-) String übergeben können?
Oder hat die IDE einfach den Typen falsch genieriert?

Die Entwicklerin schreibt mir noch:

Das ActiveX arbeitet intern NUR mit LPCSTR oder array of char. Die Kodierung in UTF-8 macht es möglich mit chinesische oder russische Zeichen zu arbeiten.
Meine Meinung nach versucht den Wrapper 2 Byte Character in 1 Byte Character zu konvertieren und das geht schief wenn der Wert über 255 (oder 127?) liegt.
Daher kommen die ?. Wenn Sie die Dateiname in UTF-8 kodieren funktioniert (ab ActiveX 1.2.4.7 mit richtige Zeichen).
Falls Sie eine Rutine benötigen um die Konvertierung zu machen können Sie folgende benutzen:
Code:
/* utf8_setc:
*  Sets a character in a UTF-8 string.
*/
int utf8_setc(char *s, int c)
{
  int size, bits, b, i;
  if (c < 128)
  {
    *s = c;
    return 1;
  }
  bits = 7;
  while (c >= (1<<bits))
    bits++;
  size = 2;
  b = 11;
  while (b < bits)
  {
    size++;
    b += 5;
  }
  b -= (7-size);
  s[0] = c>>b;
  for (i=0; i<size; i++)
    s[0] |= (0x80>>i);
  for (i=1; i<size; i++)
  {
    b -= 6;
    s[i] = 0x80 | ((c>>b)&0x3F);
  }
  return size;
}

int unicode_to_utf8n(wchar_t* src, char* dst, int srcLength, int maxOutLength)
{
  int i = 0;
  int utfsize = 0;
  int unisize = 0;
  for(i=0; i<srcLength; i++)
  {
    if (srcLength < (maxOutLength - 4))
      utfsize += utf8_setc(dst+utfsize, (int)src[i]);
    else
      break;
  }
  dst[utfsize] = 0;
  return utfsize;
}
Die obige Aussage repräsentiert meine persönliche Meinung.
Diese erhebt keinen Anspruch auf Objektivität oder Richtigkeit.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#4

AW: UTF8 als WideString an ActiveX (LPCTSTR)

  Alt 22. Mai 2012, 14:02
Du darfst den UnicodeStriong/WideString nicht "einfach" nach ANSI umewandeln.
Alles was nicht umgewandelt werden kann, wird automatisch in ein "?" übersetzt. (MSDN-Library durchsuchenWideCharToMultiBye mit '?' als Ersetzungszeichen)

Du mußt schon über die Dateisystem-APIs den Pfad übersetzen lassen.
MSDN-Library durchsuchenGetShortPathName oder Delphi-Referenz durchsuchenExtractShortPathName

Ob du das dann als ANSI oder Unicode (welches hier scheinbar intern nach ANSI umgewandelt wird) weitergibst, ist egal, da die kurzen Dateinamen eh nur ASCII benutzen.



Wenn es intern mit wirklich auch UTF-8 arbeiten kann, dann wirst du wohl ebenfalls selber nach UTF-8 übersetzen müssen.
Mußt dann nur zusehn, daß dabei irgendwo ein WideString dazwischenkommt, welcher die UFT-8-Kodierung zerstören könnte.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (22. Mai 2012 um 14:06 Uhr)
  Mit Zitat antworten Zitat
taveuni

Registriert seit: 3. Apr 2007
Ort: Zürich
533 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: UTF8 als WideString an ActiveX (LPCTSTR)

  Alt 22. Mai 2012, 15:51
Wenn es intern mit wirklich auch UTF-8 arbeiten kann, dann wirst du wohl ebenfalls selber nach UTF-8 übersetzen müssen.
Mußt dann nur zusehn, daß dabei irgendwo ein WideString dazwischenkommt, welcher die UFT-8-Kodierung zerstören könnte.
Ich glaub nicht das ich das verstanden habe. Was meinst mit "es"?

Vergessen wir mal den Dateinamen.
Es gibt noch andere Funktionen/Parameter welche in Delphi in der *_TLB.pas als WideString definiert sind
und vom ActiveX intern als UTF8 codierte LPCSTR Strings erwartet werden.

Besteht mit der Konstellation wie beschrieben eine Chance oder muss das ActiveX
angepasst werden?
Die obige Aussage repräsentiert meine persönliche Meinung.
Diese erhebt keinen Anspruch auf Objektivität oder Richtigkeit.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#6

AW: UTF8 als WideString an ActiveX (LPCTSTR)

  Alt 22. Mai 2012, 19:17
Und du bist dir wirklich sicher, daß LPCSTR bei dir als UTF-8 verwendet werden kann, bzw. kann man irgendwo den verwendeten Charset einstellen?

Wenn es unter D6 mit LPCSTR nur ANSI verarbeitet wurde, dann wird es, bei gleicher Schnittstelle auch jetzt immernoch nur als ANSI arbeiten.


Wie sieht den die TLB aus?
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
taveuni

Registriert seit: 3. Apr 2007
Ort: Zürich
533 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: UTF8 als WideString an ActiveX (LPCTSTR)

  Alt 22. Mai 2012, 20:07
Hallo himitsu,

Ich bin mir insofern sicher als dass in anderen Programmiersprachen dieses so dem ActiveX als Array of Char
übergeben kann und dieses (das ActiveX) dies richtig verarbeitet. Allerdings habe ich natürlich die Sourcen des ActiveX nicht.

Auszug aus der TLB

Delphi-Quellcode:
// *********************************************************************//
// DispIntf: _DGeheimeFirmaActiveXControl
// Flags: (4112) Hidden Dispatchable
// GUID: {EC277D05-8AA2-41F5-91AA-8EE7DBD55C77}
// *********************************************************************//
  _DGeheimeFirmaXControl = dispinterface
    ['{EC277D05-8AA2-41F5-91AA-8EE7DBD55C77}']

    function DlmXBackup(ulCameraFilter: Integer; ulStartTimeStampSec: Integer;
                        ulStartTimeStampMillis: Integer; ulStopTimeStampSec: Integer;
                        ulStopTimeStampMillis: Integer; const strFilename: WideString;
                        const strFormat: WideString): Integer; dispid 21;

    function DlmXConfig(const strConfigXML: WideString): Integer; dispid 25;
Bei der Funktion DlmXBackup gehts hier um den Parameter strFilename.
In der Funktion DlmXConfig kann/muss ich vorgängig dieses XML mitgeben:

Code:
<DlmSDK><DlmConfig><Display CodePage=“utf-8” /></DlmConfig></DlmSDK>
<DlmSDK><DlmConfig><Display CodePage=“ISO-8859-1” /></DlmConfig></DlmSDK>
<DlmSDK><DlmConfig><Display CodePage=“windows-1251” /></DlmConfig></DlmSDK>
Wird damit vielleicht das Charset eingestellt?
Die obige Aussage repräsentiert meine persönliche Meinung.
Diese erhebt keinen Anspruch auf Objektivität oder Richtigkeit.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#8

AW: UTF8 als WideString an ActiveX (LPCTSTR)

  Alt 22. Mai 2012, 23:42
Hmmm.

Also ein Problem ist ersmal, daß seit mindestens Delphi 2009 (hab nie im 2007er nachgesehn) die Delphi-Strings (AnsiString, RawByteString, UTF8String, also alle AnsiString-Nachfahren und natürlich der neue UnicodeString) über eine CodePage-Information verfügen.

Anhand dieser CodePage wird notfalls eine Convertierung vorgenommen.
Delphi erkennt also, daß du einen UTF-8-kodierten String (AnsiString+CP_UTF8) an einen Unicode-String (WideString) übergeben willst und wandelt den enthaltenen Text "korrekt" um ... macht also aus dem UTF-8 wieder Unicode.

Das andere Problem ist, daß wir nicht wissen wie Windows das, bzw. deren Code, intern aus dem WideString/PWideChar einen PAnsiChar/LPCSTR macht.
(das müßtest du mal erdebuggen oder eben ausprobieren)

Versuch es mal so:
Delphi-Quellcode:
function WUConvert(const S: string): WideString;
var
  A: UTF8String;
begin
  A := UTF8Encode(S);
  SetCodePage(A, CP_ACP, False);
  Result := A;
end;

// und falls es doch nicht geht, dann eventuell so?

function WUConvert(const S: string): WideString;
var
  A: UTF8String;
begin
  A := UTF8Encode(S);
  SetCodePage(A, $FFFF, False);
  Result := A;
end;

// oder

function WUConvert(const S: string): WideString;
var
  A: UTF8String;
  i: Integer;
begin
  A := UTF8Encode(S);
  SetLength(Result, Length(A));
  for i := 1 to Length(A) do
    Result[i] := A[i];
end;

PS: Dein <DlmSDK><DlmConfig><Display CodePage="..." /></DlmConfig></DlmSDK> ist eh nur ASCII, drum kann man sich dort alles sparen und kann es problemlos direkt übergeben.

PPS: Sicher daß “ und ” korrekt sind und nicht eigentlich " dort hingehört?
Ein korrektes XML ist das so jedenfalls nicht.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
taveuni

Registriert seit: 3. Apr 2007
Ort: Zürich
533 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: UTF8 als WideString an ActiveX (LPCTSTR)

  Alt 23. Mai 2012, 09:43
Hallo himitsu,

SetCodePage erwartet einen RawByteString.
Ich habe bei den ersten zwei Funktionen den UTF8String durch diesen ersetzt.
Die letzte lässt sich nicht kompilieren.

Mit der ersten Variante funktionierts!
Es ist mir noch nicht ganz klar weshalb.
Kannst Du mich aufklären?

UTF8Encode(s) hatte ich ja schon gemacht.
Nun ist "nur" noch das SetCodePage hinzugekommen.

Auf jeden Fall danke ich Dir vielmals. Du hast meine Woche gerettet.
Ich hoffe Du kannst Dein profundes Wissen auch beruflich angemessen einsetzen.
Die obige Aussage repräsentiert meine persönliche Meinung.
Diese erhebt keinen Anspruch auf Objektivität oder Richtigkeit.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#10

AW: UTF8 als WideString an ActiveX (LPCTSTR)

  Alt 23. Mai 2012, 10:03
UTF8Encode setzt als Codepage CP_UTF8, was eigentlich auch richtig so ist.
Mit SetCodePage wurde die Codepage nun auf $FFFF gesetzt, was einem RawByteString entspricht.
Wenn man jetzt diesen AnsiString/RawByteString an einen UnicodeString oder WideString zuweist, dann nutzt Delphi die Codepage für die Convertierung.
Es macht also implizit paraktisch ein UTF8Decode, da in den WideString Unicode reingehört.
Über den RawByteString, welcher nun dein UTF-8 enthält, aber über SetCodePage+CP_ACP gesagt bekommen hatte er enthält "angeblich" ANSI, wird nun bei der Umcodierung nicht von UTF8 nach Unicode, sondern von ANSI nach Unicode umgewandelt, also so als wenn es ANSI-Zeichen währen.

Intern wird anscheinend ebenfalls immer nur von Unicode nach ANSI umgewandelt, egal was du als Setting vorgegeben hast.
Da hätte die Entwicklerin selber für eine korrekte Konvertierung sorgen müssen.

PS: Bis mindestens Delphi 7 hat Delphi alles in einem AnsiString auch als ANSI angesehn, selbst wenn man vorher ein UTF-8 dort reingeschoben hatte.
Dort gab es die CodePage an jedem String noch nicht und somit hätte man damals UTF-8 problemlos nutzen können, ohne soeinen Krampf durchzumachen.

Aber eigentlich ist die Entwicklerin Schuld, denn wenn die den WideString auch als Unicode nutzen und dann intern korrekt umwandeln würde, dann müßte man nicht versuchen in dem Unicode-String ein verstümmeltes UTF-8 mitgeben zu müssen.


Und du mußt aufpassen, denn wir in Deutschland haben kein MultiByte im ANSI, sondern nur eine SingleByte-Codepage ... jedes Byte ist ein Zeichen.
Die Asiaten haben ein paar mehr Zeichen, drum nutzen sie eine richtige MultiByte-CodePage.

Außerdem gibt es für einige Unicode-Zichen mehrere/verschiedene ANSI-Darstellungen.
Es könnte also Probleme bei der Rückumandlung geben, da das UTF-8 implizit ein gemapptes über ANSI umgeleitet wird, mit Hin- (ANSI>Unicode) und Rückübersetzung (Unicode>ANSI), vobei das UTF-8 eventuell zerstört werden könnte.


So, ich hoffe mal, ich hab jetzt keinen Knoten im Hirn.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (23. Mai 2012 um 10:06 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:36 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz