![Delphi Loves C++ C++ Love Delphi | Embarcadero RAD Studio Delphi C++Builder Blogs How To Use A C++ DLL In Any Delphi Program](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2021/08/delphi_cplusplus_love-8391235.jpg?resize=1140%2C694&ssl=1)
There is a glorious wealth of useful C++ libraries available on the internet. We have featured many great uses of C++ here on this blog too. C++ is typically extremely high performance. If we can have the source code of the C++ library, we can create a package that will then allow us to use C++ in our Delphi programs. Often, though, the source code of the C++ library is not available. In commercial C++ libraries, it is common to get only a few C++ headers and the static library file (.lib) without any of the accompanying .cpp source files. So, in this case, when we want to use those C++ libraries in our Delphi application, we can use a Proxy DLL to make it possible.
This is great it you are looking to integrate existing C++ code into Delphi. If you want to write new C++ code, you can use C++Builder which is a part of RAD Studio. It provides a streamlined integrated experience for C++ developers.
Table of Contents
How to create a Proxy DLL to connect C++ DLL and Delphi?
To connect Delphi to a DLL, the DLL should expose a simple Windows API style API instead of C++ things. We can use any of the C++ compilers to compile the Proxy DLL.
Embarcadero Dev-Cpp Open Source Compiler
C++Builder which is the C++ side of RAD Studio supports building package files (BPL) which can be used by Delphi directly. The great thing about C++Builder is that it integrates so closely with Delphi itself. You can use Object Pascal files from within C++Builder and the C++ BPL files from within Delphi. Find out more information.
Now, let’s take a simple example. Let’s think we have a DLL file and a harder file with this declaration and no .cpp file with the implementation. You can refer to the source code of this example in this link:
https://github.com/PacktPublishing/Delphi-High-Performance/tree/master/Chapter%208/StaticLib1
1 2 3 4 5 6 7 8 9 10 |
#pragma once class CppClass { int data; public: CppClass(); ~CppClass(); void setData(int); int getSquare(); }; |
Here’s how to use a C++ library in a Delphi program with a proxy dll
Now we need to create the proxy DLL.
Create a new C++ DLL project with your preferred IDE.
![New Proxy DLL Project | Embarcadero RAD Studio Delphi C++Builder Blogs How To Use A C++ DLL In Any Delphi Program = New Proxy DLL Project](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2021/07/New-Proxy-DLL-Project-6806748.png?resize=750%2C432&ssl=1)
It will automatically add “dllmain.cpp” file. But we need another unit to wrap the static library. Add new unit called “StaticLibWrapper.cpp”.
Now we should include the header file of the static library we want to import in our project.
1 2 |
#include "stdafx.h" #include "CppClass.h" |
Now copy the header file of the static library to the project folder. Now we should include the static library in our project. To do that add the static library folder to the library directories:
![Import Static Library | Embarcadero RAD Studio Delphi C++Builder Blogs How To Use A C++ DLL In Any Delphi Program import static library](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2021/08/Import-Static-Library-8212767.png?resize=750%2C432&ssl=1)
Or in Visual Studio goto “Configuration Properties | Linker | General | Additional Library Directories settings”.
How to mark C++ DLL functions as “exported”
Now we define a Macro to mark DLL functions are exported.
1 |
#define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__) |
Next, implement the IndexAllocator class to cache the C++ objects. This class contains an array of pointers. It has three functions as “Allocate”, “Release” and “Get” to store the pointer in the cache, release the cache, and get a pointer by index.
1 2 3 |
bool Allocate(int& deviceIndex, void* obj) bool Release(int deviceIndex) void* Get(int deviceIndex) |
Then we need to Initialize and Finalize functions to allocate and deallocate IndexAllocator objects.
1 2 |
extern "C" int WINAPI Initialize() extern "C" int WINAPI Finalize() |
Then we create an instance of CppClass class and store it in the cache with this function.
1 |
extern "C" int WINAPI CreateCppClass (int& index) |
In this statement, we use “C” to make sure the same name is exported and WINAPI to change the calling conversion. DestroyCppClass is similar to this. Next, take a look at the main export functions “CppClass_setValue” and “CppClass_getSquare”. When the user calls these functions, it will get the object from the cache and call those functions and take the value.
1 2 3 4 5 6 7 8 9 10 11 |
extern "C" int WINAPI CppClass_setValue(int index, int value) { #pragma EXPORT CppClass* instance = (CppClass*)GAllocator->Get(index); if (instance == NULL) return -1; else { instance->setData(value); return 0; } } |
1 2 3 4 5 6 7 8 9 10 11 |
extern "C" int WINAPI CppClass_getSquare(int index, int& value) { #pragma EXPORT CppClass* instance = (CppClass*)GAllocator->Get(index); if (instance == NULL) return -1; else { value = instance->getSquare(); return 0; } } |
The first function will get an index of the object and set the value of the variable. In the second function, it takes the index of the object, calls the “getSquare” function of the object, and store the value in the value variable.
How to use the C++ Proxy DLL in a Delphi Application?
We can link DLLs either statically or dynamically. With static loading, the DLL will be loaded when the application starts. With dynamic loading, the DLL will not load until we call the “LoadLibrary”. Let’s use static loading for this example. Let’s declare the functions exported in the DLL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
const CPP_CLASS_LIB = 'DllLib1.dll'; function Initialize: integer; stdcall; external CPP_CLASS_LIB name 'Initialize' delayed; function Finalize: integer; stdcall; external CPP_CLASS_LIB name 'Finalize' delayed; function CreateCppClass(var index: integer): integer; stdcall; external CPP_CLASS_LIB name 'CreateCppClass' delayed; function DestroyCppClass(index: integer): integer; stdcall; external CPP_CLASS_LIB name 'DestroyCppClass' delayed; function CppClass_setValue(index: integer; value: integer): integer; stdcall; external CPP_CLASS_LIB name 'CppClass_setValue' delayed; function CppClass_getSquare(index: integer; var value: integer): integer; stdcall; external CPP_CLASS_LIB name 'CppClass_getSquare' delayed; |
We should call the “Initialize” function when our Delphi application is created and call the “Finalize” function when our application is destroyed. Then when we are using the Proxy DLL in our Delphi code, first we must call “CreateCppClass” to create an object. It will set the class ID to use in the future. Then we can call all the functions of the DLL and finally we should call “DestroyCppClass” function to destroy the class instance. In our example, we do it like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
procedure TfrmCppClassDemo.btnImportLibClick(Sender: TObject); var idxClass: Integer; value: Integer; begin if CreateCppClass(idxClass) <> 0 then ListBox1.Items.Add('CreateCppClass failed') else if CppClass_setValue(idxClass, SpinEdit1.Value) <> 0 then ListBox1.Items.Add('CppClass_setValue failed') else if CppClass_getSquare(idxClass, value) <> 0 then ListBox1.Items.Add('CppClass_getSquare failed') else begin ListBox1.Items.Add(Format('square(%d) = %d', [SpinEdit1.Value, value])); if DestroyCppClass(idxClass) <> 0 then ListBox1.Items.Add('DestroyCppClass failed') end; end; |
Finally the Delphi application will work like this:
![Delphi CppClass Import | Embarcadero RAD Studio Delphi C++Builder Blogs How To Use A C++ DLL In Any Delphi Program = delphi cppclass import](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2021/08/Delphi-CppClass-Import-4395916.png?resize=664%2C346&ssl=1)
RAD Studio allows you to rapidly create Delphi and C++ programs which can work on Windows, macOS, Linux, iOS and Android. Bring your program ideas to the devices your customers actually use by downloading a free trial today!
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition