Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi [COM] out PSafeArray (https://www.delphipraxis.net/141979-%5Bcom%5D-out-psafearray.html)

AThurm 20. Okt 2009 06:53


[COM] out PSafeArray
 
Hallo,
ich habe folgende Schnittstelle:

Delphi-Quellcode:
ITest = interface(IUnknown)
    ['{1E554409-41E9-4D3A-9D09-D8B240422DED}']
    function VorlagenHolen(const kategorieId: WideString; out pRetVal: PSafeArray): HResult; stdcall;
  end;
ich bekomme es nicht hin den Out Parameter PSafeArray in Delphi zu holen.
Oder funktioniert das nicht ein Array von Objekten abzureifen über COM ?

Andersrum hab ich es schon hinbekommen: (ein Array an COM zu übergeben)
Delphi-Quellcode:
aType := VarType(TestCom);
aArray := VarArrayCreate([0, Liste.Count], aType);

aArray[0] := Liste[0];
aArray[1] := Liste[1];
...

AnComUebergeben(PSafeArray(TVarData(aArray).VArray));

MarcoWarm 20. Okt 2009 07:12

Re: [COM] out PSafeArray
 
Hi,

Hier ein Beispiel, wie du ein SafeArray in ein Array of Byte wandelst... alle Anderen Arraytypen sollten analog funktionieren:

Delphi-Quellcode:
function SafeArrayToBytes(const si: PSafeArray): TBytes;
var
  nLow, nHigh, nSize: integer;
  pData: Pointer;
begin
  //Copy from Variant Array to Delphi array
  SafeArrayGetLBound(si, 1, nLow);
  SafeArrayGetUBound(si, 1, nHigh);
  nSize := SafeArrayGetElemsize(si);
  SetLength(Result, nSize * (nHigh - nLow + 1));

  SafeArrayAccessData(si, pData);
  CopyMemory(@Result[1], pData, Length(Result));
  SafeArrayUnaccessData(si);
end;
Gruß
Marco

AThurm 20. Okt 2009 07:17

Re: [COM] out PSafeArray
 
Du bist schon zu weit, ich scheiter ein schritt vorher:

Delphi-Quellcode:
test : PSafeArray;

TestCom.VorlagenHolen('blub', test);
bringt eine AccessViolation... die Liste wird aber schon in C# erzeugt...

sirius 20. Okt 2009 08:11

Re: [COM] out PSafeArray
 
Wie meinst du Accessviolation? Wenn in der Methode ein Fehler auftritt müsste es doch nur einen FehlerWert in HResult geben aber keine AV.

Edit: Hier mal meine Methoden:
Delphi-Quellcode:
procedure TRun.ReadValues;
var j,i:Integer;
    AnalogPSA,digitalPSA:PSafeArray;
    timestamp:TDateTime;
    varvalues:Variant;
begin
  FInputfile.GetOriginValues(i,timestamp,AnalogPSA,DigitalPSA); //SafeArrays ohne Initialisierung
  varValues:=SafeArraytoVariant(DigitalPSA);
  //...
  x:=varValues[2]; //als Beispiel
end;

//........................................................
//dazu das
function SafeArrayGetVartype(psa: PSafeArray; out varType:Word):HResult; stdcall;
  external 'oleaut32.dll' name 'SafeArrayGetVartype';

function SafeArraytoVariant(const psa:PSafeArray):Variant;
var vtype:word;
begin
  SafeArrayGetVartype(psa,vtype);
  Result:=null;
  TVarData(Result).VType := vtype or varArray;
  TVarData(Result).VArray := pointer(psa);
end;


//............................................................
//und die Deklaration:
procedure GetOriginValues(aIndex: Integer; out aTimestamp: TDateTime;
                              out aAnalogValues: PSafeArray; out aDigitalValues: PSafeArray); safecall;
//was ja dasselbe ist wie:
function GetOriginValues(aIndex: Integer; out aTimestamp: TDateTime;
                              out aAnalogValues: PSafeArray; out aDigitalValues: PSafeArray):HResult; stdcall;
Allerdings ist die COM-Klasse auch von mir und das Befüllen der Werte sieht letztendlich so aus:
Delphi-Quellcode:
//aDigitalValues entspricht DigitalPSA
  aDigitalValues:=SafeArrayCreate(st_Integer,1,bound);
  try
    SafeArrayAccessData(aDigitalValues,pData);
    try
      piData:=pData;
      for i:=0 to FDigitalCount-1 do begin
        ix:=1 shl i;
        if (digital[i div 16] and ix)=ix then value:=1
                                         else value:=0;
        piData^:=value;
        inc(piData);
      end;
    finally
      SafeArrayUnAccessData(aDigitalValues);
    end;
  except
    on e:Exception do
    begin
      SafeArrayDestroy(aDigitalValues);
      raiseError(LoadStr(eValues)+linefeed+e.Message);
    end;
  end;
Vielleicht hilft dir diese Auskunft.

Neutral General 20. Okt 2009 08:14

Re: [COM] out PSafeArray
 
Ich schätze er muss vorher Speicher reservieren für

Delphi-Quellcode:
test : PSafeArray;
Weil ers nicht tut, krachts in

Delphi-Quellcode:
TestCom.VorlagenHolen

AThurm 20. Okt 2009 08:18

Re: [COM] out PSafeArray
 
Zitat:

Zitat von Neutral General
Ich schätze er muss vorher Speicher reservieren für

Delphi-Quellcode:
test : PSafeArray;
Weil ers nicht tut, krachts in

Delphi-Quellcode:
TestCom.VorlagenHolen

nur wie ? und wieviel ? muss ich größte seperat noch von C# an Com weitergeben ?

Neutral General 20. Okt 2009 08:21

Re: [COM] out PSafeArray
 
Mhhh.. Oft wirds so gemacht, dass die Function die Länge/Größe des Arrays z.B. zurückgibt wenn man nil übergibt.

d.h. :

Delphi-Quellcode:
var len: Integer;
begin
  len := TestCom.VorlagenHolen('blub', nil);
  GetMem(test,SizeOf(PSafeArray));
  SetLength(test^,len);
  TestCom.VorlagenHolen('blub', test);
end;
So in etwa.

Ich garantiere aber für nichts :mrgreen:

sirius 20. Okt 2009 08:25

Re: [COM] out PSafeArray
 
@NG: Du brauchst bei einem SafeArray mehr Informationen als nur die Größe, um es zu erstellen. Wie willst du das machen?

Neutral General 20. Okt 2009 08:32

Re: [COM] out PSafeArray
 
Ehm...

Bin jetzt von einem "normalen" Array ausgegangen weil ich ehrlich gesagt nicht weiß was ein PSafeArray ist, bzw nicht wusste, dass es etwas spezielles ist.

Wie ist denn so ein Array definiert?

sirius 20. Okt 2009 08:33

Re: [COM] out PSafeArray
 
Zitat:

Zitat von Neutral General
Wie ist denn so ein Array definiert?

So hier:
http://msdn.microsoft.com/en-us/library/ms893380.aspx

Edit: Allerdings könnte in der Doku stehen, dass es bspw. immer ein eindimensionales Integer-Array ist. Dann braucht man wirklich nur noch die Größe.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:30 Uhr.
Seite 1 von 2  1 2      

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