String konverzió

String konverzió
2013-09-09T20:08:44+02:00
2013-09-11T06:36:16+02:00
2022-08-17T14:10:32+02:00
Lacko71
Sziasztok!

A következő problémával szembesültem, amit kb. 1 napja nem bírok megoldani.
Van egy Delphi-s DLL-em, amit C# DLL-ből hívok.
A delphis oldalon az eljárásokból PAnsiChar-ok jönnek vissza C# felé, amit teljesen jól fel tudok dolgozni. Ez egy normál, egytagú string esetében rendben is van. Ott vannak a bajok, amikor már összetettebb a visszatérési érték, több dologból halászom össze, pl.:

Result := spGetTempDirectory.Parameters.ParamByName('@Path').Value + '\Temporary User Files' + FCurrentUserName;

Itt az FCurrentUserName WideString, a ParamByName-es tag Variant, és a kettő között még egy normál string is van. A kérdésem az lenne, hogy ezt hogy lehetne PAnsiChar-rá konvertálni, hogy a DLL-ből, mint visszatérő paramétert feldolgozhassam? Próbáltam WideString-el is, de érdekes módon, a C#-os oldalon csak az első pár karakter jelent meg.
Köszönöm a segítségeket!
Mutasd a teljes hozzászólást!

  • Neked nem WideString gondod van? Ugye az 2 byte-os.
    A konvertálás nem így működik?

    var s: AnsiString; w: WideString; p: PAnsiChar; ... s := p; w := WideString(s);
    Mutasd a teljes hozzászólást!
  • Köszi, közben ezzel próbálkoztam:

    function GetTempDirectory: PWideChar; stdcall; var wideChars : array[0..1024] of WideChar; myString : String; begin spGetTempDirectory.ExecProc; mystring:= VariantToPWideChar(spGetTempDirectory.Parameters.ParamByName('@Path').Value) + '\Temporary User Files' + FCurrentUserName; StringToWideChar(myString, wideChars, 1024); Result:=wideChars; end;


    function VariantToPWideChar(v:variant): PWideChar; Var s : String; p: PWideChar; begin s:=v; GetMem(p,Length(s)*Sizeof(WideChar)); StrCopy(p, PWideChar(s)); Result:=p; end;

    Ezzel a C#-os oldalon meg is jelent a végeredmény!
    Azonban, a DLL több funkciót is tartalmaz, így egy másiknál elakadt a fordítás:

    IndexNames := IndexNames + wideChars;

    Miért nem lehet PWideChar-okat összeadni, mint egy normál stringet?
    Itt az IndexNames egy kimenő, out paraméter, és PWideChar típusú. A sor egy ciklusban található, a wideChars a fentiekhez hasonlóan képződik, a ciklus során mindig más értékkel. Az eredmény egy hosszú PWideChar lenne, de az összeadásnál elhal.
    Tehát nekem mindenképp PWideChar-t kell visszaadnom, nem jó a DLL-ben a WideString típusú paraméter.
    Mutasd a teljes hozzászólást!
  • A fordítás ezt az üzenetet dobja:

    [DCC Error]: E2015 Operator not applicable to this operand type
    Mutasd a teljes hozzászólást!
  • PWideChar = ^WideChar;
    Tehát pointer.
    IndexNames := IndexNames + wideChars;
    Két pointert adsz össze és nem a tartalmakat.
    WideCharToString(...) kell ...
    Mutasd a teljes hozzászólást!
  • Köszi a tippet!
    A WideCharToString működik, jól összerakom vele az átadandót.
    Mindez addig jól is megy, amíg egy normál funkcióeredményről van szó:

    function GetTempDirectory(out IFN: PWideChar): PWideChar; stdcall;

    De amint az IFN-nek adok át a függvény belsejében, a C#-os oldalon a következő hiba keletkezik:

    {"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}

    A C#-os oldal:

    string ki; string gt = GetTempDirectory(out ki); MessageBox.Show(gt + " " + ki);

    A "fejléc":

    [DllImport("InvoiceGstore.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)] public static extern string GetTempDirectory(out string ki);

    Valamenyik oldalon nagyon nem frankó valami.
    Van valami tippetek?
    Köszi!
    Mutasd a teljes hozzászólást!
  • Nem is tudom, de string az nem wide alapban.

    Próbáld meg byte[] :

    [DllImport("InvoiceGstore.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)] public static extern string GetTempDirectory(out byte[] ki);

    Utána a ki

    string val = Encoding.UTF8.GetString(ki); string val = Encoding.Unicode.GetString(ki);
    Mutasd a teljes hozzászólást!
  • Szia,
    Ok, közben úgy csináltam, hogy egyszerre csak 1 paraméterátadás legyen delphi oldalon, hogy kiszűrhessem, melyiknél van a baj:
    1. a normál átadásnál
    2. az out-os, visszatérő paraméternél.

    Érdekes, hogy az out-os rendesen visszaadja ha Delphi oldalon Widestring-el határozom meg!

    A delphi-s kód:

    function GetTempDirectory(): WideString; stdcall; begin Result:='valami'; end;

    C# oldal:

    [return: MarshalAs(UnmanagedType.LPStr)] <-- lehet, hogy ez a baj? public static extern string GetTempDirectory(); .... .... string ki; ki = GetTempDirectory(); <--itt a gond MessageBox.Show(ki);
    Mutasd a teljes hozzászólást!
  • 1 Answer

    Mintha ezt írtam volna...
    Mutasd a teljes hozzászólást!
  • Már nagyon közel vagyunk a megoldáshoz, ezt csináltam most:

    [return: MarshalAs(UnmanagedType.LPArray)] public static extern byte[] GetTempDirectory(); ..... ..... byte[] ki = GetTempDirectory(); string ki_ = Encoding.UTF8.GetString(ki); MessageBox.Show("ki = GetTempDirectory() " + ki_);

    Ez a hiba:
    Cannot marshal 'return value': Invalid managed/unmanaged type combination.

    Van tipped erre?
    Mutasd a teljes hozzászólást!
  • Van tipped erre?

    Van neki, megpedig ez: Terj at QT-re.
    Mutasd a teljes hozzászólást!
  • Talán így:

    public static extern IntPtr GetTempDirectory();
    Mutasd a teljes hozzászólást!
  • C++ wxWidgetre írtam.
    Ma már kevesen használják.
    Mutasd a teljes hozzászólást!
  • A GetTempDirectory() függvény fejléce és kifejtése Delphi-s DLL-ben van:

    function GetTempDirectory(): WideString; stdcall;

    A C# oldalon nem bírom lekezelni a visszatérőt, de közben áttúrtam már a netet, de a fenti, korábbi bejegyzésemhez hasonlókat kaptam eredményül...de nem működik!
    Jó lenne a byte[]-os megoldás, de a managed/unmanaged hiba lép fel. Szerintem valami ennél nem jó:

    [return: MarshalAs(UnmanagedType.LPArray)] public static extern byte[] GetTempDirectory();
    Mutasd a teljes hozzászólást!
  • Van neki, megpedig ez: Terj at QT-re
    Mutasd a teljes hozzászólást!
  • Nézd ezt meg?
    itt
    Mutasd a teljes hozzászólást!
abcd