|
Yes Philippe, you are right: IMHO the solution offered in the article is not outdated, it is a good solution, a linker independent solution and a more controlled solution than the linker v6.0 offered. Personally I like the solution and I am going to use it.
But I think that the article is outdated because actually the linker offer a direct solution that I suspect the author didnt know when he wrote it (I dont knew the linker solution not even the author solution before read them). It is an easy solution that would be remarked. The linker solution was pointed in a thread response, ok, but I think this solution deserve to appear in a more remarked position.
I think that maybe the author must to have the righ to modify his article introduction, that's all.
And again you are right, the author solution is very useful when you need to use a dll whose name isn't even knwon at compile time. However (I am not sure but...) the /DELAYLOAD solution seem to solve this situation too, developing your own helper function.
I think that the author solution has another notable virtue: it is a solution with a very low overhead, there is not hidden hooks or callbacks, only a function pointer, thats all. The programmer can add his own call controls when he need. For example, if you need to call a dll function repeatedly in a exhaustive for loop then maybe you prefer to check (one time) that the dll and function pointer are ok before going to do the for loop instead of check it before every time you want to call it.
Thanks a lot
Arbesto
|
|
|
|
|
Philippe, with all due respect -- I really confused trying to understand you:
>>
What about loading DLLs whose name isn't even known at compile time?
<<
I thought, that's the purpose of the article as well as proposed DELAYLOAD approach... Name of DLL may not be known -- however entrypoints should be defined... That's sure what plug-ins are...
So, please, clarify, what exactly did you mean???...
|
|
|
|
|
Perhaps I am not familar enough with the DELAYLOAD mechanism.
For me, you specify the DLL to be used at link time (thus giving its name), but the DLL is loaded only when needed.
From a quick glance at MSDN, it seems that's the "regular" way of doing things, perhaps there are some smart workarounds for this limitation.
So, you have to specify all the DLLs that have to be loaded by the program, at link time.
Plug-ins are, by definition, written after the release of the program, so they are loaded by the program when giving their names by initialization data (good old INI files or equivalents, registry, environment, you name it).
If there is a way to use DELAYLOAD with unknown DLLs, I will be curious to know.
Mmm, I reread your second message... I understand it better than yesterday, I think. You mean that you specify /delayload:x.dll, but on the callback, you load another library instead, and the delayload mechanism loads the preset functions of the given DLL instead.
Well, you still have to do a LoadLibrary, you just avoid the GetProcAddress. It seems to be a bit convoluted a solution to this simple problem. DELAYLOAD is useful when there are a lot of functions to load, but plug-ins often have only a few exposed functions, so it seems a bit of an overkill. Not all tools are suited for all purposes.
Regards.
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
|
|
|
|
|
Philippe, I almost regreat that I've started that discussion...
Sure, if you consider that "you still have to do a LoadLibrary, you just avoid the GetProcAddress. It seems to be a bit convoluted a solution to this simple problem." So, if you consider "convoluted solution" direct function call, compared to pointer to function call -- really there is nothing to talk about here... Not to mention necessary duplicate function declarations...
That's really nothing I could say...
GL
I
|
|
|
|
|
Don't regret anything, and don't take it personnaly.
We just exchange ideas, and express our opinions. There not such a thing as "the right method".
This discussion may be useful for those pondering which method to use, as we expose advantages and inconvenients of both.
The choice is then left to those implementing the solutions.
Direct function call vs. pointer function call.
I use the following method:
typedef char * (*STR_F_t)();
STR_F_t GetString;
GetString = (STR_F_t)GetProcAddress(g_hInstDllLib, "GetString");
This way, whether I choose to link the DLL or load it dynamically, I call the functions the same way.
Duplicate function declarations.
I agree, it adds quite some overhead/work. One can automate the generation of such declarations, but it is still a hassle to create and maintain.
But for plug-ins, as I said, the number of functions is quite low, so it may not be critical.
Last note: I know that 95% (wild guess ) of CP readers use Visual Studio 6 or .NET, but for those with lower version (?) or users of alternate compilers (Borland, gcc, Mars, etc.), the traditional method still works.
Regards.
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
|
|
|
|
|
OK, Philippe -- As I said DELAYLOAD has some advantages and some disadvantages -- nothing is for free in that world...
I also, never argued against article proposition, even more I'm using close to that Article approach for about 10 years now...
However, I would like to see -- how would you approach the task of Dynamically loading MFC Exported Class for example...
Would love to see your manually created file with hundreds of mengled typedefs and GetProcAddresses...
GL
I
|
|
|
|
|
Anonymous wrote:
never argued against article proposition
I never said that, it is Arbesto that was a bit over enthousiastic and stated that the article was outdated.
Anonymous wrote:
how would you approach the task of Dynamically loading MFC Exported Class for example
Actually, I don't do MFC, unless required by my employer But I see your point, depending on the need, one tool is better suited that other. Although if you mean to load MFC42.dll, for example, a hardcoded binding seems more suitable, since the program need it inconditionnaly.
I you mean to load a MFC-based class, like those given on CP, I probably choose DELAYLOAD, or at worse, as I said, I would generate the binding with a script.
Thank you for this interesting discussion, I hope it will give some hindsight to readers. At least, I will sure consider using DELAYLOAD now
Regards.
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
|
|
|
|
|
Philippe Lhoste wrote:
Anonymous wrote:
never argued against article proposition
I never said that, it is Arbesto that was a bit over enthousiastic and stated that the article was outdated.
I am sorry if my first email has supposed any kind of discussion and misinterpretation for the opinions manifested by others.
I explained why I consider the article was outdated, maybe it was a problem with my dictionary What about "the article has an old introduction"?. I say this because I think that is a pity that the DELAYLOAD solution will be relegated to the messages zone instead of figure in the article introduction, that was all.
My apologizes again,
Arbesto
|
|
|
|
|
Arbesto Pelta wrote:
maybe it was a problem with my dictionary
Or maybe mine
I saw "outdated" and interpreted "obsolete"...
But you are right, the subject deserves a full article comparing the various methods to bind a DLL.
Regards.
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
|
|
|
|
|
|
I cant answer your question but I have some comments on your article.
I really cant find the advantage of using the macros. Wouldn´t it be better to make a function instead of the macro. Then could also be the testing and error checking implemented.
Try this @ home. (B&B)
|
|
|
|
|
The thread below about the suitability of using COM instead of this simple approach reminds me of the hype that SOAP is being given these days. Many folks suggest everyone to switch to SOAP in every occasion instead of resorting to good old GETs and POSTs with some custom return format, without a second thought on the burden imposed by this huge technology, both in terms of efficiency and complexity of development. In many situations, what could have been dealt with in a couple of hours worth of coding becomes a major nightmare, just for the sake of the promised flexibilty SOAP is supposed to bring along. Sure SOAP can be great for middle to large projects, but most of the time it adds next to nothing to a simpler approach.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Agree
|
|
|
|
|
Excellent article, only an additional macro for simplify the declaration when you like to use the original function name in the class func pointer:
#define INIT_DLL_TWIN_FUNCTION(ret, cc, func, params) \
if (m_hDLL) \
{ \
func = (ret (cc* )params)GetProcAddress(m_hDLL, #func); \
} \
else \
func = NULL; \
if (!func) \
bOk = false;
And the idea:
I have modified the code for my use. I have defined a variable to store the dll name and load this name in the constructor.
Then the Init method (and a new Uninit) load (and unload) the dll using this name.
When I like to load and unload the dll I use this two methods (I need this facility in my code).
And one question: What is the better solution to get the interface information about one DLL to design easily a CDllModule derived class for it?
Thanks for a tiny and useful solution.
|
|
|
|
|
Thank you, you solve the big problem for me
|
|
|
|
|
INIT_DLL_FUNCTION_BY_ORDINAL (retrieving a function by number) would be usefull sometimes.
I like this and will borrow some ideas from your code (I need slightly more complicated solution, e.g. "default" empty functions)
Thanks !
WTL
|
|
|
|
|
Why reinventing all that stuff, when the OS comes with it?
COM offers interfaces (set of functions) which can be identified uniquely.
There are two ways of loading them:
1) The OS way: the DLL and its classes/interfaces have to be registered - The the OS will load them for you. But from your description this is not want you looking for.
2) The manual way: Use LoadLibrary as before. Then the DLL should register its interface(s) dynamically during startup by means of "CoRegisterClassObject".
Your main program can request the interfaces normally with "CoGetClassObject".
The COM stuff might be a little strange at the beginning. But it offers many advantages compared to the old-style DLL programming.
Good luck,
Ingo.
|
|
|
|
|
I know what com does. but the regular dll has its reason to exist.
|
|
|
|
|
I did'nt tell you not to use a DLL. The interfaces or whatever have nothing to do with the container in which they are in (EXE, DLL).
What is your "reason"???
Greetings,
Ingo.
|
|
|
|
|
Think about tons of existing C code and old fasion projects.
Anyway, thank you for your suggestion.
|
|
|
|
|
Ingo Kellpinski wrote:
But it offers many advantages compared to the old-style DLL programming.
like what?
-c
Garbage collection, making life better - for weenies!
|
|
|
|
|
For example:
- identify the syntax + semantic = version of an interface by an UUID:
This is the most important reason and important for compatibility and extensibility of interfaces.
- decouple the interface from the object/algorithm implementation:
The interface of a component has nothing to do with a specific object. An object may offer an interface and another object of a different kind may offer the same interface among others. With interfaces the objects only show a very small part of their implementation (better encapsulation).
- possibility to offer different implementations (in-proc server, exe, remote server, ...)
- OS support for the interface use:
e.g. no manual LoadLibrary calls, management of instances, management of mutual exclusion in multi-threaded environments, ...
- description of objects and interfaces in a portable interface definition language:
The interface description is machine and human readable documentation and also implementation base. This may go over platform borders.
- in case of "Dual-Interfaces" a script language may scan the interface and use its semantic dynamically
...I think there are many more reasons but the above crossed my mind most quickly.
Greetings, Ingo.
|
|
|
|
|
Ingo Kellpinski wrote:
identify the syntax + semantic = version of an interface by an UUID
big deal. with a DLL, you change the function name, if you need to change its signature. if the interface changes, you still have to recode the things that use it.
Ingo Kellpinski wrote:
decouple the interface from the object/algorithm implementation
this is not a problem with standard DLLs, either.
Ingo Kellpinski wrote:
possibility to offer different implementations
OK. this is good.
Ingo Kellpinski wrote:
no manual LoadLibrary calls,
instead, you get the joys of reference counting.
Ingo Kellpinski wrote:
description of objects and interfaces in a portable interface definition language
C is portable to far more platforms than MIDL.
in my experience, COM is usually much more trouble than it's worth. the only times COM has been useful for me is in cases where there is no alternative: COM+ for doing web server components, for example. otherwise, it's just a big, fat, clumsy wrapper around LoadLibrary/GetProcAddress.
-c
Garbage collection, making life better - for weenies!
|
|
|
|
|
Chris Losinger wrote:
Ingo Kellpinski wrote:
possibility to offer different implementations
OK. this is good.
No, it is'nt
Especially this solution is designed to offer different implementations of some interface. Just prepare another DLL with the same interface. This (I mean different implementations) is the only reason of using dynamic DLL loading.
WTL
|
|
|
|
|
true
-c
Garbage collection, making life better - for weenies!
|
|
|
|
|