I want to change and test my dll function build for an application without constantly closing and starting the application itself, which takes a lot of time. Hence I build a calling dll for the application to load, and another testing dll (which i load dynamically), where I can change my testing function in real time, without closing the application.
The application loads automatically the calling dll, wherein I can dynamically load my testing dll and call an empty function succesfully :
calling dll:
typedef void(__stdcall *test_func)(void);
HINSTANCE hdl = LoadLibraryA("C:\\testingfunction.dll");
test_func func = (test_func) GetProcAddress(hdl, "?testingfunc##YAXXZ");
func();
In the testing function dll I have:
testingfunction.h
#define DLL_API _declspec(dllexport)
DLL_API void __stdcall testingfunc();
testingfunction.cpp
DLL_API void __stdcall testingfunc()
{
double a = 3 * 4.2;
//PlugIn::gResultOut << " ...I am alive... " << std::endl;
return;
}
So if the printing line is commented out, the function works in the application, meaning it does not crash. But when I uncomment the printing line, the application crashes. It seems I cannot use the methods and functions of the application itself.
How would I fix this? Do I need to use __declspec(dllimport), and if so, how?
thanks!
Related
I have BCB5 dll with method:
extern "C" void __declspec(dllexport) __stdcall SM(TDataSource *DS) {
TForm *form = new TForm(Application);
form->Width = 300;
form->Height = 300;
form->Name = "frm";
TDBGrid *grd = new TDBGrid(form);
grd->Parent = form;
grd->Name = "grd";
grd->Align = alClient;
grd->DataSource = DS;
form->ShowModal();
}
When I call this method from C++ builder 5 application, it's working fine.
try {
typedef void __declspec(dllexport) __stdcall SM(TDataSource *DS);
SM *Upload;
HINSTANCE hDll = LoadLibrary("main.dll");
Upload = (SM*) GetProcAddress(hDll,"SM");
Upload(DataSource1);
FreeLibrary(hDll);
}
catch (Exception *ex) {
ShowMessage(ex->Message);
}
But, if I'm trying to call this method from C++ XE 5 application, I get Access Violation.
Is there a way to solve the problem of data transmission from XE 5 application to BCB 5 dll without recompile dll in XE5?
It is not safe to pass/use RTL/VCL objects over the DLL boundary like you are doing, unless both EXE and DLL are compiled with Runtime Packages enabled so that they share a common instance of the same RTL and VCL frameworks (but then you have to deploy the RTL/VCL BPL binaries with your app).
Your DLL doesn't work in XE5 because the DLL is expecting the BCB5 version of the TDataSource component, not the XE5 version. No, they are not compatible, as they have different memory layouts and dependancies.
So your choices are to either:
recompile the DLL in XE5, and live with the risk that passing TDataSource over the DLL boundary is not safe in general, unless you enable Runtime Packages.
re-write the DLL to be a Runtime Package (BPL) instead. Then passing TDataSource between EXE and DLL is safe. However, Runtime Packages are version-specific, so you will need to compile separate BPLs if you need to continue using the code in both BCB5 and XE5.
re-write the DLL to not pass a TDataSource over the DLL boundary to begin with. Figure out another interop-safe way to exchange data between EXE and DLL.
I want to call this delphi code via a DLL from C++
procedure MyMessage; stdcall;
begin
ShowMessage(DLLName + ' more text');
end;
Using some delphi test code I see no problem , but from C++ no message box is shown.
i did the following C++ coding
// function prototype
typedef void(__stdcall*VoidCall)();
// prototype for info function inside DLL
extern "C" __declspec(dllimport) void __stdcall MyMessage();
MyMessage = (VoidCall)::GetProcAddress(load, "MyMessage");
MyMessage;
As I want to use as a next steps existing delphi forms with a wrapper DLL from C++ , I guess the solution of this problem will also enable me for the next task ....
The presented C++ code does not compile. It mixes binding of a dll via an import library with dynamic loading of a dll via LoadLibrary / GetProcAddress.
To load a DLL created with Delphi, it is easiest to use dynamic loading of the dll. Do this as follows:
// function prototype
typedef void(__stdcall*VoidCall)();
[...]
// Load the library
HMODULE lib = LoadLibrary("Project1.dll");
if (lib != 0)
{
__try
{
// Get the address to the exported function in the DLL
// and store it in the variable myMessageFunction
VoidCall myMessageFunction = (VoidCall) GetProcAddress(lib, "MyMessage");
// Call the function. Note you need the parenthesis even
// when there are no parameters to pass
myMessageFunction();
}
__finally
{
// Unload the library again. Note that you cannot use
// functions from the library after that. So only unload
// the dll once you don't need it anymore.
FreeLibrary(lib);
}
}
else // TODO: Error handling, dll cannot be loaded
If you want to use load time linking, you can create a *.lib file to be used with C++ for a DLL created with Delphi. Use the solution from this question.
I was searching through stackoverflow questions but none of them answered my question. I have a game engine and I want to load player AI (written in c++) in runtime.
Click on button, file dialog appears
Choose file with AI (.dll or something?)
Click on 'start' button, game starts using AI's that I add.
AI could be a method or whole class, it doesn't matter. I think I should generate .dll but I not sure how to do that. This class should look like this:
class PlayerAI
{
void computeSomething(list of argument, Object& output)
{
// some logic
}
}
Assuming pure Windows platform since none specified -
If you want to inject DLL, first obtain a handle to it using LoadLibrary-function like so:
HINSTANCE handleLib;
handleLib = LoadLibrary(TEXT("YourDLL.dll"));
You may then obtain a function pointer to a specific function in the lib. Like this:
FUNC_PTR func;
func = (FUNC_PTR) GetProcAddress(handleLib, "yourFunc");
Then you can call the function like so:
(func) (L"TESTSTRING HERE");
When done, call FreeLibrary(libhandle)
How to declare a function as exported is in VS for instance like this (this is needed to mark your function in your DLL that you precompile:
__declspec(dllexport) int __cdecl yourFunc(LPWSTR someString)
{
//Code here...
}
Since you mention already compiled DLLs, you want to look at LoadLibrary and GetProcAddress. That's how you do runtime loads of DLLs and extract specific functions from them.
Examples can be found under Using Run-Time Dynamic Linking.
I have created a project that uses 2 DLL's to play against each other (a DLL is a player). The game is that the first player picks a number and the second player picks another number, and then the PlayRound function compares the two numbers. My problem that am not sure how to load the DLL (run/load time). I created my first DLL (simple.dll) which has a Pick function that always returns "int 2" for simplicity:
#include "stdafx.h"
#define ASEXPORT
#include <iostream>
#include "player.h"
using namespace std;
int Pick(int Round, int MyMoves[], int OpponentMoves[])
{
return 2;
}
This project have a header (player.h) with the following code:
#ifndef ASEXPORT
#define DLLIMPORTOREXPORT dllimport
#else
#define DLLIMPORTOREXPORT dllexport
#endif
_declspec(DLLIMPORTOREXPORT) int Pick(int Round, int MyMoves[], int OpponentMoves[]);
Not sure where to include this code do i include it in the main or in a function:
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
// Get a handle to the DLL module.
//hinstLib = LoadLibrary(TEXT(player2Name));
hinstLib = LoadLibrary();
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "simple.DLL");
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
(ProcAdd) (L"Message sent to the DLL function\n");
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// Report any failures
if (! fRunTimeLinkSuccess)
printf("Unable to load DLL or link to functions\n");
if (! fFreeResult)
printf("Unable to unload DLL\n");
//
I hope I made it easy to understand
You can see this in my ModuleService implementation in the IndieZen core library. I treat .dll and .so as a "module". In my plugin system I have a standard that every module implements one and only one exported function, which is getModule() in my example, Pick() in your use case.
My example returns in implementation of I_Module interface. In my example, modules are collections of plugins, so the only thing you can do is get an implementation of an I_Plugin, which in turn can be used to gain access to class factories, and then these class factories construct objects (extensions) which implement pre-defined interfaces (extension points).
I know that's all overkill for your example, but the code is quite easy to follow; feel free to copy/paste the subsets you can use.
One key thing is to NOT use _declspec(DLLIMPORTOREXPORT) on the Pick function; you should only be exporting the function and not importing it. You should also not be linking these DLL's to your main application, nor should you include the DLL's header file into your main application. This will give you the flexibility of being able to import two separate DLL's that expose the same function (Pick in your case) without having linking errors. It will also give you the advantage of not knowing the names of the DLL's until runtime (where possibly you may want some configuration or GUI to let the user pick which players).
My implementation, with the reference counting, class factory, etc would give you an added advantage in that you could have two players implemented within the same DLL which could play against each other.
I'm trying to create a dll that contains a VCL data module - the idea being that various applications can all load the same dll and use the same database code.
The data module itself is tested ok as part of an application - I've copied the form over to my dll project.
So in the dll entry point method, I need to initialize the data module:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
//if I don't call this, I get an exception on initializing the data module
CoInitialize(NULL);
//initialize a standard VCL form; seems to works fine
//I'm not using Application->CreateForm as I don't want the form to appear straight away
if(!MyForm) MyForm = new TMyForm(Application);
//this doesn't work - the thread seems to hang in the TDataModule base constructor?
//I've also tried Application->CreateForm; same result
if(!MyDataModule) MyDataModule = new TMyDataModule(Application);
}
I've also seen something about how I need to call Application->Initialize before creating the form but this doesn't seem to make any difference.
Any ideas?
Thanks
You really should not be doing very much work in your DllEntryPoint() at all. Certainly not calling CoInitialize(), anyway. It is not the DLL's responsibility to call that when loaded. It is the calling app's responsibility before loading the DLL.
You should either:
export an additional function to initialize your DLL and then have the app it after loading the DLL (same for uninitialing the DLL before unloading it)
don't create your TForm/TDataModule until the first time the DLL actually needs them.
move your TForm/TDataModule into their own worker thread inside the DLL. In this case, you would then call CoIniitalize().
And in all cases, don't relay on the DLL's Application object to manage the lifetime of your TForm/TDataModule. Free them yourself instead before the DLL is unloaded.