Watch, Follow, &
Connect with Us

Features and tips

Categories:



Archives:



Explicit DLL load from Delphi

You may also want to call your DLL function directly from Delphi. No more comments, just a sample code:

program A;
{$APPTYPE CONSOLE}
uses Windows, System.SysUtils;
var
  res : Integer;
  dll_handle: THandle;
  MyFunction: function(param: integer): Integer stdcall;
begin
  res := 0;
  dll_handle := LoadLibrary('My.DLL');
  if (0 <> dll_handle)
  then begin
    @MyFunction := GetProcAddress(dll_handle, '_DllFunction');
    if (NIL <> @MyFunction)
    then begin
      res := MyFunction(1);
    end;
    FreeLibrary(dll_handle);
  end;
  WriteLn(res);
end.

As you can see this is a same C++ code but re-written on Embarcadero XE3 Delphi.

And what is DLL code? In Embarcadero XE3 C++ it would be just:

extern "C" int _libmain(unsigned long reason)
{
  return 1;
}
extern "C" __stdcall __declspec(dllexport) int DllFunction(int par)
{
  return par + 1;
}
Posted by miso on October 22nd, 2012 under Uncategorized | 1 Comment »


Implicit and Explicit DLL loading

DLL could be loaded implicitly or explicitly. Another way is Static Linkage that allows placing all required functions to your program to avoid DLLs usage at all, but it is out of this post.
Implicit DLL loading is having your program to load DLL before main() called. You specify DLL’s library name already when linking a program; it will work with that exact version of DLL and will not even start without.
Implicit load pros/contras:
+ Simple
+ Program will either start or not
- Longer loading
- Depends on exact DLL version
Explicit DLL loading allows loading DLL when only needed, like a plug-in. After DLL loaded you call its functions by known names and then unload.
Explicit load pros/contras:
+ Compatible with future DLL versions
+ Flexibility
- React delay
- DLL incompatibility could be discovered too late
Let us think that My.DLL has this function:

extern "C" __stdcall __declspec(dllexport) int DllFunction(void);

I will describe syntax later; here I just place minimal code for both DLL usage types.
Implicit.cpp:

extern "C" __stdcall __declspec(dllimport) int DllFunction(void);
int main() {
    return DllFunction();
}

Explicit.cpp:

#include <windows.h>
extern "C" __stdcall __declspec(dllimport) int DllFunction(void);
int main() {
    int res = 0;
    HINSTANCE dll_handle = LoadLibrary("My.DLL");
    FARPROC func_addr;
    typedef int (__stdcall * pfVoidRetInt)(void);
    pfVoidRetInt MyFunction;
    if (dll_handle) {
        func_addr = GetProcAddress(HMODULE(dll_handle), "_DllFunction");
        if (func_addr) {
            MyFunction = pfVoidRetInt (func_addr);
            res = MyFunction();
        }
        FreeLibrary(dll_handle);
    }
    return res;
}

I prefer 2nd variant though.

Posted by miso on October 5th, 2012 under Uncategorized | Comment now »


Entry point routine in RAD XE3 created DLL


Typical DLL has an entry point. This is a function with a specific name which linker aware of.

When DLL is loaded or unloaded this function is called; that helps to init DLL data or release resources. If you need this you should implement such a function. On RAD-built DLL load/unload, DLL itself automatically calls first matched function from this list: DllEntryPoint(), DllMain(),and last _libmain(). If more than one co-exists, others will be optimized-out, i.e. only best match will reside in DLL and it will be called. You should not call such function directly from program that loads DLL, hence they are not __declspec(dllexport) marked.

DllMain() is a known Windows DLL entry point while other two are RAD-specific.

Although Wizard-made _libmain() code could be enough you sometimes may need another variant of entry point, so here I place all variants in one place:

#include <windows.h>

//Actual DLL entry point:

void MyEntryPoint(const unsigned long reason, const int value)

{

if (DLL_PROCESS_ATTACH == reason)

{

//Initialization code

}

else if (DLL_PROCESS_DETACH == reason)

{

//Resources releasing code

}

}

//BCC native DLL entry point:

extern "C" int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)

{

MyEntryPoint(reason, 1);

return 1;

}

//Typical Windows DLL entry point:

extern "C" int WINAPI DllMain(HINSTANCE hinst, unsigned long reason, void* lpReserved)

{

MyEntryPoint(reason, 2);

return 1;

}

//BCC default entry point

extern "C" int _libmain(unsigned long reason)

{

MyEntryPoint(reason, 3);

return 1;

}

In this example both DllMain() and _libmain() will be optimized out; those are here only for syntax example.

You better know what to place under DLL_PROCESS_ATTACH and what under DLL_PROCESS_DETACH branches.

Posted by miso on October 3rd, 2012 under Uncategorized | Comment now »


Creating simple DLL using RAD XE3

I will dig to details assuming you have already read this article:

http://docwiki.embarcadero.com/RADStudio/en/Creating_Packages_and_DLLs

In order to create a simple DLL in Embarcadero RAD XE3 create a new DLL project:

File|New|Other…|C++BuilderProjects|Dynamic-linkLibrary

Set it: C++ = On, Target Framework = None, Multi Threaded = On

You will already have some code like:

extern "C" int _libmain(unsigned long reason)

{

return 1;

}

Save and build; open your build folder like:

C:\Users\YourName\Documents\RAD Studio\Projects\Win32\Debug

Most important files there are: Project1.dll (DLL itself), Project1.lib (library file), Project1.map, and Project1.tds.

You can load this DLL to your program, use it, and unload… or not? Not yet. Dependency Walker could warn that your DLL is missing another one, CC32120MT.DLL from BDS folder bin. You either correct your system path to find that DLL, or place it next to your DLL. Remember to follow License agreement to respect copyright though.

Now you can try using it simplest way – execute next command line to just load and unload:

regsvr32.exe /u Project1.dll

Among warnings, this utility says that your DLL “was loaded”, this is important. If you got this message you can go next steps in DLL development.

Posted by miso on October 3rd, 2012 under Uncategorized | Comment now »




Server Response from: BLOGS1