{"id":2444,"date":"2011-09-25T01:56:32","date_gmt":"2011-09-24T23:56:32","guid":{"rendered":"https:\/\/iguanademos.com\/Jare\/wp\/?page_id=2444"},"modified":"2011-09-25T01:58:38","modified_gmt":"2011-09-24T23:58:38","slug":"loadlibrary-getprocaddress-fun","status":"publish","type":"page","link":"https:\/\/iguanademos.com\/Jare\/wp\/?page_id=2444","title":{"rendered":"LoadLibrary-GetProcAddress Fun"},"content":{"rendered":"<p>(Note: this article first appeared as a <A HREF=\"http:\/\/www.flipcode.com\/cgi-bin\/msg.cgi?showThread=Tip-LoadLibraryGetProcAddress&#038;forum=totd&#038;id=-1\" TARGET=\"_blank\">Tip Of The Day<\/A> in <A HREF=\"http:\/\/www.flipcode.com\" TARGET=\"_blank\">Flipcode<\/A>. The C++ to HTML formating comes from Kurt&#8217;s internal tools)<\/p>\n<p>I explain a macro trick used by the authors of the BASS sound library to help with dynamic loading of the DLL; then I introduce a way to make it even easier to apply. Afterwards I extend the idea with a modified macro + a header file trick which useful by itself. 3 totds in one! \ud83d\ude42<\/p>\n<p>Last night, adding the sound library BASS (visit http:\/\/www.un4seen.com\/music\/) to a pet project, I noticed they had added and documented a nice trick to help people who want to load the DLL at runtime instad of static-linking it. The trick is in the way all the functions in the DLL&#8217;s header file bass.h are declared:<\/p>\n<table border=0 cellspacing=0 cellpadding=10 width=\"90%\">\n<tr>\n<td bgcolor=\"#ffffff\">\n<pre>\r\n<font face=\"Courier, Courier New\" color=\"#000000\">\r\nBOOL BASSDEF(BASS_GetDeviceDescription)(<font color=\"#0000ff\">int<\/font> devnum, <font color=\"#0000ff\">char<\/font> **desc);<\/font><\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>i.e. with the macro BASSDEF surrounding the function name. This macro is defined at the beginning:<\/p>\n<table border=0 cellspacing=0 cellpadding=10 width=\"90%\">\n<tr>\n<td bgcolor=\"#ffffff\">\n<pre>\r\n<font face=\"Courier, Courier New\" color=\"#000000\">\r\n<font color=\"#0000ff\">#ifndef<\/font> BASSDEF\r\n<font color=\"#0000ff\">#define<\/font> BASSDEF(f) WINAPI f\r\n<font color=\"#0000ff\">#endif<\/font>\r\n\r\n<font color=\"#007f00\">\/\/ The declaration above is, after the macro substitution, a plain old <\/font>\r\nfunction <font color=\"#0000ff\">declaration<\/font>:\r\nBOOL WINAPI BASS_GetDeviceDescription(<font color=\"#0000ff\">int<\/font> devnum, <font color=\"#0000ff\">char<\/font> **desc);<\/font><\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>Normally, if you want to load a DLL at runtime and GetProcAddress() the functions you want, you are forced to declare your own function pointer vars with the right parameter declaration. However, in BASS, when you include the header file, you can simply do<\/p>\n<table border=0 cellspacing=0 cellpadding=10 width=\"90%\">\n<tr>\n<td bgcolor=\"#ffffff\">\n<pre>\r\n<font face=\"Courier, Courier New\" color=\"#000000\">\r\n<font color=\"#0000ff\">#define<\/font> BASSDEF(f) (WINAPI *f) <font color=\"#007f00\">\/\/ define the functions as pointers<\/font>\r\n<font color=\"#0000ff\">#include<\/font> \"bass.h\"\r\n\r\n<font color=\"#007f00\">\/\/ The declaration above is now interpreted differently:<\/font>\r\nBOOL (WINAPI *BASS_GetDeviceDescription)(<font color=\"#0000ff\">int<\/font> devnum, <font color=\"#0000ff\">char<\/font> **desc);<\/font><\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>and instead of the useless (for dynamic loading) function declarations, you have obtained a list of function pointer variables with the right parameters. Cool! Now it&#8217;s up to you to write:<\/p>\n<table border=0 cellspacing=0 cellpadding=10 width=\"90%\">\n<tr>\n<td bgcolor=\"#ffffff\">\n<pre>\r\n<font face=\"Courier, Courier New\" color=\"#000000\">\r\nBASS_GetDeviceDescription = GetProcAddress(bass, \"BASS_GetDeviceDescription\");<\/font><\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>for each function you want, and then call BASS_GetDeviceDescription(-1, &#038;pInfo) just like you normally would. What a cool tip of the day, right?<\/p>\n<p>WRONG! You missed type checking. A C++ compiler will complain that BASS_GetDeviceDescription is of type int (__stdcall *)(int, char**), while GetProcAddress() returns a int (__stdcall *)(void) value. DAMN! We&#8217;re right where we started because we have to typecast each GetProcAddress separately, and to do so we need the right parameters again.<\/p>\n<p>Instead of that mess, we can do some weird typecast trickery:<\/p>\n<table border=0 cellspacing=0 cellpadding=10 width=\"90%\">\n<tr>\n<td bgcolor=\"#ffffff\">\n<pre>\r\n<font face=\"Courier, Courier New\" color=\"#000000\">\r\n*(<font color=\"#0000ff\">void<\/font>**)&BASS_GetDeviceDescription=(<font color=\"#0000ff\">void<\/font>*)GetProcAddress(bass, \"BASS_GetDeviceDescription\");<\/font><\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>Since we already know the funcptr variables have the correct types (because they come from the official header), we can simply coerce the compiler into treating them as (void*) variables during the assignment, and avoid repeating the function declarations. I ended up using a macro to further simplify things:<\/p>\n<table border=0 cellspacing=0 cellpadding=10 width=\"90%\">\n<tr>\n<td bgcolor=\"#ffffff\">\n<pre>\r\n<font face=\"Courier, Courier New\" color=\"#000000\">\r\n<font color=\"#0000ff\">#define<\/font> INITBASSF(f) *(<font color=\"#0000ff\">void<\/font>**)&f=(<font color=\"#0000ff\">void<\/font>*)GetProcAddress(bass, #f)\r\n\r\n   INITBASSF(BASS_Init);\r\n   INITBASSF(BASS_Start);\r\n   INITBASSF(BASS_Stop);\r\n   INITBASSF(BASS_Free);\r\n   INITBASSF(BASS_GetInfo);<\/font><\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>There&#8217;s even more! We still have to write our list of funcptr initializations. Should we forget one, the funcptr variable will be uninitialized, trying to call it may cause major havok. I know this is a minor burden since you will catch most errors right away in a debug build; however, can we automate this further? YES! They could have separated the function declarations into their own header file (without any single-include guards), with the standard BASSDEF macro taking also the parameter declaration as a macro parameter:<\/p>\n<table border=0 cellspacing=0 cellpadding=10 width=\"90%\">\n<tr>\n<td bgcolor=\"#ffffff\">\n<pre>\r\n<font face=\"Courier, Courier New\" color=\"#000000\">\r\n<font color=\"#007f00\">\/\/ Inside \"Bass.h\"<\/font>\r\n<font color=\"#0000ff\">#define<\/font> BASSDEF(f,p) WINAPI f p\r\n...\r\n<font color=\"#0000ff\">#include<\/font> \"BassFunctions.h\"\r\n\r\n<font color=\"#007f00\">\/\/ BassFunctions.h:<\/font>\r\nBOOL BASSDEF(BASS_GetDeviceDescription, (<font color=\"#0000ff\">int<\/font> devnum, <font color=\"#0000ff\">char<\/font> **desc));\r\n<font color=\"#0000ff\">void<\/font> BASSDEF(BASS_SetBufferLength, (<font color=\"#0000ff\">float<\/font> length));\r\n<font color=\"#007f00\">\/\/... the rest of the BASSDEF function declarations<\/font><\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>With that little help bit, my MusicPlayer.cpp wrapper file would look something like this:<\/p>\n<table border=0 cellspacing=0 cellpadding=10 width=\"90%\">\n<tr>\n<td bgcolor=\"#ffffff\">\n<pre>\r\n<font face=\"Courier, Courier New\" color=\"#000000\">\r\n<font color=\"#0000ff\">#define<\/font> BASSDEF(f,p) (WINAPI *f) p <font color=\"#007f00\">\/\/ define the functions as pointers<\/font>\r\n<font color=\"#0000ff\">#include<\/font> \"Bass.h\"\r\n<font color=\"#007f00\">\/\/....<\/font>\r\n<font color=\"#0000ff\">bool<\/font> CMusicPlayer::Init()\r\n{\r\n   HINSTANCE bass=LoadLibrary(\"BASS.DLL\"); <font color=\"#007f00\">\/\/ load BASS<\/font>\r\n   <font color=\"#0000ff\">if<\/font> (!bass) <font color=\"#0000ff\">return<\/font> <font color=\"#0000ff\">false<\/font>;\r\n\r\n   <font color=\"#0000ff\">#undef<\/font> BASSDEF\r\n   <font color=\"#0000ff\">#define<\/font> BASSDEF(f,p) *(<font color=\"#0000ff\">void<\/font>**)&f=(<font color=\"#0000ff\">void<\/font>*)GetProcAddress(bass, #f)\r\n   <font color=\"#0000ff\">#include<\/font> \"BassFunctions.h\"\r\n   <font color=\"#007f00\">\/\/ Your initialization here....<\/font>\r\n}<\/font><\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>And there you have it. No maintenance burden, no typing mistakes, no need to repeat a list of names. With the original BASS header file built the way I propose, you only need 6 lines of code to switch from static to dynamic linking.<\/p>\n<p>I have used the &#8220;declarator macro + listing include file&#8221; technique quite a few times, in situations well unrelated to DLLs, Windows, Visual C or games altogether, so I guess any C++ programmer can benefit from it. \ud83d\ude42 For instance, you have a series of enumerated type constants and you want to have them available also in string form (say, to read the constant in string form from a text script file):<\/p>\n<table border=0 cellspacing=0 cellpadding=10 width=\"90%\">\n<tr>\n<td bgcolor=\"#ffffff\">\n<pre>\r\n<font face=\"Courier, Courier New\" color=\"#000000\">\r\n<font color=\"#007f00\">\/\/ UnitIdList.h<\/font>\r\nDECLARE_ID(UNITID_SOLDIER)\r\nDECLARE_ID(UNITID_WORKER)\r\nDECLARE_ID(UNITID_MACHINE)\r\nDECLARE_ID(UNITID_RESOURCE)\r\n\r\n<font color=\"#007f00\">\/\/ UnitId.h<\/font>\r\n<font color=\"#007f00\">\/\/...<\/font>\r\n<font color=\"#0000ff\">#define<\/font> DECLARE_ID(a) a,\r\n<font color=\"#0000ff\">enum<\/font> TUnitId\r\n{\r\n<font color=\"#0000ff\">#include<\/font> \"UnitIdList.h\"\r\n   UNITID_INVALID\r\n};\r\n<font color=\"#007f00\">\/\/...<\/font>\r\n\r\n<font color=\"#007f00\">\/\/ somewhere in my cpps...<\/font>\r\n<font color=\"#0000ff\">#include<\/font> \"UnitId.h\"\r\n\r\n<font color=\"#0000ff\">#undef<\/font> DECLARE_ID\r\n<font color=\"#0000ff\">#define<\/font> DECLARE_ID(a) { a, #a },\r\n<font color=\"#0000ff\">static<\/font> <font color=\"#0000ff\">struct<\/font> { <font color=\"#0000ff\">int<\/font> id; <font color=\"#0000ff\">const<\/font> <font color=\"#0000ff\">char<\/font> *pszId; }\r\ns_aUnitIds[] =\r\n{\r\n<font color=\"#0000ff\">#include<\/font> \"UnitIdList.h\"\r\n};\r\n\r\nTUnitId FindUnitIdFromStringID(<font color=\"#0000ff\">const<\/font> <font color=\"#0000ff\">char<\/font> *pszId)\r\n{\r\n   <font color=\"#0000ff\">for<\/font> (<font color=\"#0000ff\">int<\/font> i = 0; i &lt; ARRAY_LEN(s_aUnitIds); i++)\r\n     <font color=\"#0000ff\">if<\/font> (0 == stricmp(s_aUnitIds[i].pszId, pszId))\r\n       <font color=\"#0000ff\">return<\/font> s_aUnitIds[i].id;\r\n   <font color=\"#0000ff\">return<\/font> UNITID_INVALID;\r\n}<\/font><\/pre>\n<\/td>\n<\/tr>\n<\/table>\n","protected":false},"excerpt":{"rendered":"<p>(Note: this article first appeared as a Tip Of The Day in Flipcode. The C++ to HTML formating comes from Kurt&#8217;s internal tools) I explain a macro trick used by the authors of the BASS sound library to help with &hellip; <a href=\"https:\/\/iguanademos.com\/Jare\/wp\/?page_id=2444\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":2432,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-2444","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/iguanademos.com\/Jare\/wp\/index.php?rest_route=\/wp\/v2\/pages\/2444","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/iguanademos.com\/Jare\/wp\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/iguanademos.com\/Jare\/wp\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/iguanademos.com\/Jare\/wp\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/iguanademos.com\/Jare\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2444"}],"version-history":[{"count":2,"href":"https:\/\/iguanademos.com\/Jare\/wp\/index.php?rest_route=\/wp\/v2\/pages\/2444\/revisions"}],"predecessor-version":[{"id":2447,"href":"https:\/\/iguanademos.com\/Jare\/wp\/index.php?rest_route=\/wp\/v2\/pages\/2444\/revisions\/2447"}],"up":[{"embeddable":true,"href":"https:\/\/iguanademos.com\/Jare\/wp\/index.php?rest_route=\/wp\/v2\/pages\/2432"}],"wp:attachment":[{"href":"https:\/\/iguanademos.com\/Jare\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2444"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}