All my posts

Wednesday, February 16, 2011

Working with C++ dll's from ObjectPascal

It's a well known fact that there are many excelent libraries written in C++, and we, as Object Pascal programmers can take advantage of them.

Many times, I have found in forums or mailing lists, questions such as "How can I translate XYZ library to ObjectPascal?", or "How can I use a C++ from Object Pascal?". Well, it's not necessary to translate a library from C++, we can use it just by creating a C wrapper around it.

Why I need to wrap the C++ library to C?

Because of name mangling, if you look inside the library (using TDump included in Delphi, or by using "nm" on linux), you'll get something like this:

In the snippet from above, you can see names like _ZN12DcmAgeStringaSERKS. Those names may reffer to functions, methods, constants or variables we can call from Object Pascal by using GetProcAddress. The name in the example, is the "mangled" version of DcmAgeStringa.

If the C++ doesn't expose classes, but functions, you can call the functions just by passing the mangled name to GetProcAddress, but what about working with classes?.

There's no way to directly use a C++ class from Object Pascal, before using it is mandatory to create a "C" wrapper around it.

It just gets change the value of the string "str" and print its contents.

As I mentioned earlier, there's no way to create an instance of a C++ class from Object Pascal, but there's a workaround, to create a "C" wrapper around it, and export it from the library.

Creating our first "C" wrapper around a C++ class

The idea is to create plain C functions in charge of creating an instance of the Test class, then return a pointer to that instance, then create another function that receive the pointer as param, and use its getHello function.

If you look at the snippet above, you can see I added code inside an extern "C" block, there will reside the exported functions. I added three functions to create an instance of our class, to use the method getHello, and one to delete the instance.

To create a dll from this code, just do this (I'm using Linux here, but you can use MinGW from Windows using the same command):

g++ -fPIC -shared test.cpp -o test.so

That command compiles our code and creates a shared object file, in Windows you must replace "-o test.so" with "-o test.dll".

Now you can check the contents of the library by using nm or tdump. The result should be something like this:

You can see, that createTestInstance, deleteTestInstance and doHello now aren't mangled as in the plain C++ library.

Now the fun part!

The last step of this journey, is to create an Object Pascal program that loads and use the shared library. The program should do this:

1) Load the library and store a reference to its handler.2) Execute the method createTestInstance and store a reference to the pointer it returns.3) Execute the method doHello by passing the pointer stored in point 2 as parameter.4) Delete the instance by executing deleteTestInstance and passing the same pointer.