Einzelnen Beitrag anzeigen

Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
655 Beiträge
 
Delphi 12 Athens
 
#7

AW: Delphi-ActiveX-DLL in VB.Net: Problem mit Strings

  Alt 4. Apr 2012, 14:47
Hier mal ein neuer Zwischenstand, der mich aber nicht wirklich glücklicher macht:

Was das "safecall" angeht, ist das wohl eher eine Delphi-interne Geschichte, die besonders beim Import fremder ActiveX-DLLs nach Delphi relevant ist - ich suche aber ja den umgekehrten Fall. Das ist zumindest das, was ich zu dem Thema im Netz gefunden habe.

Um mal nicht direkt mit dem "großen" Visual Studio um mich zu schießen, habe ich auch mal eine 64-Bit-DLL erzeugt (und damit auch mal direkt gesehen, das wenigstens das funktioniert) und diese in ein VBScript eingebaut und aufgerufen. Ergebnis ist aber das selbe: Die Funktion, die ein Integer zurückgibt, kann ich problemlos aufrufen, aber den WideString bekomme ich nicht - der ganze Scripting-Host verabschiedet sich dann.

Nächster Ansatz: Anstelle den String direkt zurückzugeben, wird das Ergebnis in einer privaten Variable zwischengespeichert, die über die Property "LastResult" abgefragt werden kann. Funktioniert - so kommt der Text ohne Fehler sowohl bei VB.Net als auch im VBScript an. Aber das ist ja nicht das, was ich will! Es muss doch möglich sein, einen String als Rückgabewert zu haben! Ich habe selber schon (okay, in Delphi) fremde ActiveX-DLLs genutzt, die mir einen String zurückgeben. Und die DLL, die ich letztlich durch eine neue ablösen will, gibt auch die Ergebnisse fleißig als String zurück. Kann doch nicht sein, dass der aufrufende Programmierer jedes Mal dieses "LastResult" aufrufen muss. Irgendwas geht da schief... und ich finde keinen Ansatz...

Zur Verdeutlichung hier mal der Code, der "funktioniert":

Die Unit zur Implementierung:

Delphi-Quellcode:
unit teststr32_impl;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  ComObj, ActiveX, TestStr32_TLB, StdVcl;

type
  TStringOps = class(TAutoObject, IStringOps)
  private
    FLastResult: string;
  protected
    function CountStrLength(const aInStr: WideString): SYSINT; stdcall;
    function ReverseStr(const aInStr: WideString): SYSINT; stdcall;
    function Get_LastResult: WideString; safecall;
    procedure Set_LastResult(const Value: WideString); safecall;
  end;

implementation

uses ComServ;

function TStringOps.CountStrLength(const aInStr: WideString): SYSINT;
begin
  Result:=Length(aInStr);
end;

function TStringOps.ReverseStr(const aInStr: WideString): SYSINT;
var i: integer;
    tempStr: string;
begin
  tempStr:='';
  for I := length(aInStr) downto 1 do
    tempStr:=tempStr+aInStr[i];
  FLastResult:=tempStr;
  Result:=0
end;

function TStringOps.Get_LastResult: WideString;
begin
  Result:=FLastResult;
end;

procedure TStringOps.Set_LastResult(const Value: WideString);
begin
  FLastResult:=Value;
end;

initialization
  TAutoObjectFactory.Create(ComServer, TStringOps, Class_StringOps,
    ciMultiInstance, tmApartment);
end.
Und der wesentliche Ausschnitt aus der _TBL.pas sieht so aus:

Delphi-Quellcode:
// *********************************************************************//
// Interface: IStringOps
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {C97D8342-0B92-42AF-AB10-28A825B221FE}
// *********************************************************************//
  IStringOps = interface(IDispatch)
    ['{C97D8342-0B92-42AF-AB10-28A825B221FE}']
    function ReverseStr(const aInStr: WideString): SYSINT; stdcall;
    function CountStrLength(const aInStr: WideString): SYSINT; stdcall;
    function Get_LastResult: WideString; safecall;
    procedure Set_LastResult(const Value: WideString); safecall;
    property LastResult: WideString read Get_LastResult write Set_LastResult;
  end;

// *********************************************************************//
// DispIntf: IStringOpsDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {C97D8342-0B92-42AF-AB10-28A825B221FE}
// *********************************************************************//
  IStringOpsDisp = dispinterface
    ['{C97D8342-0B92-42AF-AB10-28A825B221FE}']
    function ReverseStr(const aInStr: WideString): SYSINT; dispid 201;
    function CountStrLength(const aInStr: WideString): SYSINT; dispid 202;
    property LastResult: WideString dispid 203;
  end;
Und letztlich der Aufruf im Visual Studio:

Code:
Public Class Form1
    Private Sub ButtonReverse_Click(sender As Object, e As EventArgs) Handles ButtonReverse.Click
        Dim testStr As Object
        testStr = CreateObject("TestStr32.StringOps")

        LabelResult.Text = testStr.ReverseStr(TextBoxInput.Text).ToString
        LabelResult2.Text = testStr.LastResult
    End Sub

    Private Sub ButtonLength_Click(sender As Object, e As EventArgs) Handles ButtonLength.Click
        Dim testStr As Object
        testStr = CreateObject("TestStr32.StringOps")

        LabelResult.Text = testStr.CountStrLength(TextBoxInput.Text).ToString
    End Sub
End Class
Ich weiß ja nicht mal, ob ich irgendwas falsch mache oder ob es ein Bug in Delphi ist oder irgendwo an einer COM/Net-Zwischenschicht oder im Visual Studio (letzteres glaube ich nicht, da der gleiche Fehler ja auch im VBScript auftritt).

Wer auch immer Ideen hat, her damit. Werde wohl auch mal im Emba-Forum nachfragen, vielleicht weiß dort ja jemand etwas.

Bis denn
Bommel
  Mit Zitat antworten Zitat