Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a Delphi Stream to a c/c++ DLL

Tags:

c++

stream

delphi

Is it possible to pass a Delphi stream (TStream descendant) to a DLL written in c/c++? DLL will be written in Microsoft c/c++. If that is not possible, how about if we use C++ Builder to create the DLL? Alternatively, are there any Stream (FIFO) classes which can be shared between Microsoft C/C++ and Delphi?

Thanks!

like image 934
ssh Avatar asked Aug 03 '12 21:08

ssh


Video Answer


2 Answers

You can do this using IStream and TStreamAdapter. Here's a quick example (tested in D2007 and XE2):

uses
  ActiveX;

procedure TForm1.DoSomething;
var
  MemStream: TMemoryStream;
  ExchangeStream: IStream;
begin
  MemStream := TMemoryFile.Create;
  try
    MemStream.LoadFromFile('C:\Test\SomeFile.txt');
    MemStream.Position := 0;
    ExchangeStream := TStreamAdapter.Create(MemStream) as IStream;
    // Pass ExchangeStream to C++ DLL here, and do whatever else
  finally
    MemStream.Free;
  end;
end;

Just in case, if you need to go the other way (receiving an IStream from C/C++), you can use TOleStream to get from that IStream to a Delphi TStream.

like image 187
Ken White Avatar answered Sep 27 '22 22:09

Ken White


  • Code compiled by Microsoft C/C++ cannot call methods directly on a Delphi object. You would have to wrap the methods up and present, to the C++ code, an interface, for example.
  • Code compiled by C++ Builder can call methods directly on a Delphi object.

In general, wrapping up a Delphi class and presenting it as an interface is not completely trivial. One reason why you can't just expose the raw methods via an interface is that the Delphi methods using the register calling convention which is proprietary to Embarcadero compilers. You'd need to use a calling convention that is understood by the Microsoft compiler, e.g. stdcall.

Another complication comes with exceptions. You would need to make sure that your interface methods did not throw exceptions since your C++ code can't be expected to catch them. One option would be to use Delphi's safecall calling convention. The safecall calling convention is stdcall but with an added twist that converts exceptions into HRESULT values.

All rather straight forward in concept, but probably requiring a certain amount of tedious boilerplate code.

Thankfully, in the case of TStream, you can use TStreamAdapter to expose the Delphi stream as a COM IStream. In fact, the source code for this small class shows how to handle the issues I describe above.

like image 20
David Heffernan Avatar answered Sep 27 '22 22:09

David Heffernan