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

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!

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.

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.

Related

How do I link to a native class in a C++/Cli mixed-mode dll

I have the following setup:
CSharp.dll, a C# dll
CppCli.dll, a Mixed-Mode C++/Cli dll.
Native.dll, a native C++ dll.
The native project declares
class Native
{
public:
virtual void Add(int a);
};
which is implemented in the mixed mode project:
class Mixed : public Native
{
public:
virtual void Add(int a);
ICSharpInterface^ MakeManaged();
};
Since the base class is defined in Native, I can pass my implementation to other code in native. But now I want to test this class.
If I use #pragma make_public(Mixed); it will only make a struct public, without any functions visible to the outside.
If I try to link to the mixed-mode dll from another mixed-mode dll, I get linker errors because it's a native class and the mixed-mode dll generates no .lib to link against.
And if I try to __declspec(dllexport) the class, the Visual Studio complains because the interface exposes managed stuff.
So my question is:
How do I instantiate (link to) this class in my tests? I would be happy with any solution that shows how to create an instance where I can call its public interface on, doesn't matter if from C++, C++/Cli or from C#.
You are missing an important step, you haven't yet considered how a native program is going to create an instance of the Mixed object. Which is non-trivial, it does require getting the CLR loaded and initialized so it can execute managed code. Keep in mind that the client code does not do this automatically, it doesn't know beans about the CLR, it only knows about Native.dll. There are three basic ways to get this done:
You can expose managed classes as COM objects, very simple to do with the [ComVisible] attribute. Possible to do directly from C#, you don't need the C++/CLI wrapper. The usual disadvantage is that the client code has to use COM to instantiate the object and make calls on it, not the kind of code that programmers like to write.
You can host the CLR yourself, the most efficient and flexible solution. This magazine article gives an introduction, beware that it is dated.
The C++/CLI compiler gives you a way to give you an unmanaged exported function that can execute managed code. It auto-generates a stub that gets the CLR loaded and initialized, if necessary.
Focusing a bit on the last bullet, since that's what you probably like, what you need here is a factory function, one that creates an instance of the Mixed class and returns a Native* back to the caller. So it can call ptr->Add() and invoke Mixed::Add(). That can look like this:
extern "C" __declspec(dllexport)
Native* CreateObject() {
return new Mixed;
}
Also gets you the import .lib that you can link in your native project. Do beware the disadvantages, they are significant. It is not exactly fast since the stub must check if the CLR is initialized yet and make the native-to-managed transition. The error reporting is extremely lousy since you have no decent way to diagnose exceptions that are thrown in the C# code. And memory management is an issue, the caller has to be able to successfully destroy the returned object which requires all modules to use the exact same CRT. The kind of problems that COM solves.
The exact same technique is available in C# as well by using an IL rewriter. Gieseke's unmanaged exports template is popular.

Reading structured data in VB.NET from MFC DLL function using P/Invoke

I have the following structure in an MFC DLL:
struct retornoSAP
{
enum tipoRetorno
{
Ok,
Falha,
AbrirArquivo, // mStrData válido
InserirArquivo, // mStrData válido
retornoMap, // mLstData válido
retornoTable, // mLstTable válido
retornoString, // mStrData válido
};
tipoRetorno mTipo;
CString mStrData;
CMapStringToString mLstData;
retTable* mLstTable;
CMapStringToString mLstVars;
retornoSAP( tipoRetorno pTipo )
{
mTipo = pTipo;
mLstTable = NULL;
}
~retornoSAP()
{
if ( mLstTable ) CISap::release( mLstTable );
}
};
retTable definition is:
typedef vector<CMapStringToString*> retTable;
This structure is used to store data read from an SAP API, and I have a lot of functions that return a "retornoSAP" value.
It happens that I have to call those functions from VB.NET, using P/Invoke (DllImport). I have read some material about marshaling unmanaged types to .NET (like this http://blogs.msdn.com/b/dsvc/archive/2009/02/18/marshalling-complicated-structures-using-pinvoke.aspx), and it probably would be easy to marshal a structure with some basic types in it, but I wonder if it is even possible to marshal a CMapStringToString or, even worse, a vector of CMapStringToString.
My question is if it's worth spending some time trying to translate this structure to a .NET type (in this case, where I could find some good documentation)?
If not, I wonder if it sounds like a good idea to use a XML parser in C++, write all my data to a XML structure, and then return that XML structure as a BSTR string, so I could read the BSTR return value easily it in my .NET application and parse it back to a XML structure. In that case, I would pass some big strings between the MFC DLL and the .NET application...
You can't really deal with MFC classes with P/INVOKE. I think you can choose one of two option:
Not touching the MFC dll at all: create a dll with CLI C++. Some effort to learn the language, but is a thunk dll, you don't need to study it all. This way you can expose some ref classes to .NET world and call from its methods the MFC dll. From inside the ref class you can read your original MFC structures and populate some other structures more .NET friendly.
Modify the MFC dll, expose some entry point with extern "C" decoration, in order to avoid name mangling, and convert internal structure in something easyer to manage, string as you guess, would be a not so elegant, but cutting edge solution;)
Both solution have some performance overhead, but I guess the first one would pay better, and it is sometimes the only one preventing modification to the original MFC dll, and sometimes this is desiderable. Second one is probably simpler, but passing magic string would involve some parsing leading to performance leak, possible errors so you need more test, more costs and so on.
Another drawback of solution 1 is you need an extra deploy for the C++/CLI redistributables.
I did not mention since you probably already know, but doing this kind of interop needs the .NET code compiled in x86 mode if your target C++ dll are 32 bit compiled.

Dynamic-like alternative for C++ and COM using IDispatch

I was showing a coworker how easily a COM object could be created and used in C++ using the Microsoft ATL library. In particular, I wanted to use demonstrate IDispatch to show how it can be used to dynamically call a method. However, I don't use C++/ATL frequently enough to not get lost in the templates and convenience methods and classes of ATL.
We created a small COM class, MyCOMLibrary.SimpleClass that has a single method named AppendMessage that takes 2 BSTRs and has no return value.
From a simple Win32 console application, creating and using the COM object was easy:
CComPtr<IDispatch> simpleClass;
debugPrint.CoCreateInstance(L"MyCOMLibrary.SimpleClass");
if (simpleClass) {
CComVariant vModule(L"Demo");
CComVariant vMessage(L"Welcome to COM");
simpleClass.Invoke2(L"AppendMessage", &vModule, &vMessage);
}
While this makes creating and managing the COM object nearly painless (especially when compared to using DISPPARAMS), I was looking for an even more concise way of calling the AppendMessage method that reflects modern C++/ATL/COM usage (in VS 2012).
The best case would be like C#'s dynamic keyword (dynamic documentation) (or any other "late-bound" language like JavaScript/VB6/etc):
simpleClass.AppendMessage(L"Demo", L"Welcome to COM");
Or, without that, this would be more readable:
simpleClass.Invoke2(L"AppendMessage", L"Demo", L"Welcome to COM");
However, I know the first won't compile as the method doesn't exist on CComPtr<IDispatch> and the second won't compile as Invoke2 requires VARIANTs.
I did try using the interface directly as a comparison:
// workaround VS2012 intellisense issue with #import
#ifndef __INTELLISENSE__
#import "progid:MyCOMLibrary.ISimpleClass" version("1.0")
#else
#include "Debug\MyCOMLibrary.tlh"
#endif
CComPtr<MyCOMLibrary::ISimpleClass> simpleClass;
simpleClass.CoCreateInstance(L"MyCOMLibrary.ISimpleClass");
if (simpleClass) {
CComBSTR module(L"Interfacing");
CComBSTR message(L"And, then, there was COM.");
simpleClass->AppendMessage((BSTR)module, (BSTR)message);
}
But, it's nearly identical to the original (and further, I want to do late-bound).
Question
Is there a different/shorter/better/awesome way of calling AppendMethod using IDispatch and ATL that would further impress upon my coworkers that C++ isn't always difficult? (Or, a better way without ATL would also be fine).
Take a look at VOLE by matthew wilson.
It is at http://vole.sourceforge.net/
It think it does what you want. I have used it before, and it makes IDispatch client programming a breeze.
Take a look at http://www.codeproject.com/Articles/19962/Driving-Microsoft-Word-using-VOLE for an example using Microsoft World

Is it safe to remove a call to OleInitialize from a non COM static library?

Today I had to define the WIN32_MEAN_AND_LEAN preprocessor macro in a native C++ project because I decided to use boost::asio in it, and without that macro, I get build errors.
Thing is, the error I get now is OleInitialize: identifier not found. According to the MSDN, this function is used to initialize a COM library. My project is not a COM library now, but my partners say it used to be.
In this case, would it be safe to remove the call? The project uses a mix of Win32 serial port functions and boost::asio (gradually, I'll leave just boost::asio). My concern is that OleInitialize might be necessary for some Win32 calls.
This is all it is done with it:
HRESULT hOle = OleInitialize( 0 );
if( !SUCCEEDED( hOle ) )
throw "Could not initialize OLE";
The worst that will happen is COM methods may start failing, if you're still calling some. OleInitialize() calls CoInitialize() internally. Only those functions need this. The base Win32 functions (CreateWindow, CreateFile, etc) do not require this initialization.
If you don't call any COM methods (any of the CoXXX() functions) and you don't call any Ole methods (OleXXX() functions), then you should be fine if you remove it.
You should do a quick search of your code base for COM / OLE functions and make sure you're really not using those technologies anymore. Then you can make a build where you don't do this and test it to see if it still works (you have a suite of test cases, right?).
Have a look at the Docs for other things that may break that you should check on.

How to call a JNI DLL from C++

I have a task to interface with a dll from a third party company using C++.
The dll package comes with:
the dll itself
a sample Java implementation - consists of a java wrapper(library) generated using the SWIG tool and the the java source file
documentation that states all the public datatypes, enumeration and member functions.
My other colleague is using Java(based on the example in package) to interface with the dll while I'm asked to use C++. The Java example looks straight forward... just import the wrapper and instantiate any class described in the docs..
More info on the dll:
From the docs, it says the dll was programmed using C++
From a hexdump, it shows that it was compiled using VC90 (VS C++ 2008 right?) and something from Dinkumware.
From a depends.exe output, the functions seems to be wrapped under JNI. For example: _Java_mas_com_oa_rollings_as_apiJNI_Server_1disconnect#20
My dilemma:
The dll company is not changing anything in the dll and not providing any other info.
How do i use the member functions in the class from the dll?
I did some simple LoadLibrary() and GetProcAddress and manage to get the address of the public member functions.
But i dunno how to use the functions that has the datatype parameters defined in the dll. For example:
From the docs, the member function is defined as:
void Server::connect(const StringArray, const KeyValueMap) throw(std::invalid_argument,std::out_of_range)
typedef std::map Server::KeyValueMap
typedef std::vector Server::StringArray
how do i call that function in C++. The std::map and std::vector in my compiler (VS 2005) has different functions listing that the one in the dll. For example, from the depends.exe output:
std::map // KeyValueMap - del, empty, get, has_1key,set
std::vector // StringArray - add, capacity, clear, get, isEMPTY, reserve, set, size
Any advice/strategy on how i should solve this? Is it possible to simply instantiate the class like the Java example?
If you are trying to use VS 2005 to try and interface with a DLL that is built using VS2008, your attempts will be mostly doomed unless you can use a plain C interface. Given your description, this is not the case; The runtime libraries differ between VS2005 and VS2008 so there is little chance that the object layout has stayed the same between compilers. The 'something from Dinkumware' that you're referring to is most likely the C++ standard library as ISTR that Microsoft uses the Dinkumware one.
With your above example you're also missing several important pieces of information - the types you describe (Server::StringArray and Server::KeyValueMap) are standard library containers. OK fine, but standard library containers of what? These containers are templates and unless you know the exact types these templates have been instantiated with, you're a little stuck.
Is this DLL intended to be called from C++ at all? The fact that it export a JNI interface suggests that it might not be in the first place. Does it export any other public symbols apart from those that are of the format _Java_...?
Of course if there is no other way in and you must use C++ instead of Java, you might want to look into embedding a JVM into your C++ app and use that to call through to the C++ dll. It's not what I'd call an elegant solution but it might well work.
I don't quite understand the use of C++ standard library data types here. How can Java code provide a std::map argument? Are the arguments you pass in always just "opaque" values you would get as output from a previous call to the library? That's the only way you're going to be able to make it work from code under a different runtime.
Anyway...
When you make a JNI module, you run javah.exe and it generates a header file with declarations like:
JNIEXPORT void JNICALL Java_Native_HelloWorld(JNIEnv *, jobject);
Do you have any such header file for the module?
These symbols are exported as extern "C" if I recall correctly, so if you can get the correct signatures, you should have no issues with name mangling or incompatible memory allocators, etc..
The "#20" at the end of the method signature means that the function is declared "stdcall" and that 20 bytes are put on the stack when the function is called. All these methods should start with a JNIEnv* and a jobject, these will total 8 bytes I believe, on a 32-bit environment, so that leaves 12 bytes of parameters you will need to know in order to generate a correct function prototype.
Once you figure out what the parameters are, you can generate something like this:
typedef void (__stdcall *X)(JNIEnv *, jobject, jint i, jboolean b);
Then, you can cast the result of GetProcAddress to an X and call it from your C++ code.
X x = (X)GetProcAddress(module, "name");
if (x) x(params...);
Unfortunately, what you have doesn't quite look like what I have seen in the past. I am used to having to deal with Java data types from C/C++ code, but it looks like this module is dealing with C++ data types in Java code, so I don't know how relevant any of my experience is. Hopefully this is some help, at least.