What's new

help with dll stuff

tylerbingham

New member
I am coding a .dll. and I know how to use 1 .dll( you call a pragma commment(lib,"main.dll"), but I was wondering how to use 2 .dll's in a project...................sample code problem::

// dlluser.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "main.h"

char str[255];

int main(int nNumberofArgs, char* pszArgs[])
{

cout<<"which .dll do you want to load( 1 or 2 )"<< endl << endl;
cin>>str;

if(0 == strcmp ("2",str))
{
// #pragma comment(lib,"dll2.lib")
printMessage();
}

if(0 == strcmp ("1",str))
{
// #pragma comment(lib,"dll1.lib")
printMessage();
}

return 0;
}

this does NOT WORK!!!!, I want a way to pick which .dll loads.
Any help would be much appreciated.

p.s. I know you can't use the pragma directive this way, but I am all out of ideas!!
 

Doomulation

?????????????????????????
You can use loadlibrary. It works perfecly with 2 or more dlls... :ermm: I never heard of this "pragma" thingie...you're using c++, right?

PHP:
pLib = LoadLibrary("library.dll");
 

Azimer

Emulator Developer
Moderator
You are better off using LoadLibrary. Using #pragma is run at the preprocessor level. You can not change use a compile-time conditional with it.
 

Cyberman

Moderator
Moderator
for loading multiple DLL's using LoadLibrary is the way. HOWEVER you need to include function pointers to the DLL resources in the DLL's.

use GetProcAddress() to get pointers to the functions in the DLL.
GetProcAddress returns a pointer to a type void..
You will need to type cast the pointer returned to your function pointers then you can use them as functions.

A few tips do not pass objects or such things to a DLL this is a sure fire path to disaster. Especially if you are using a different compilor than the what the DLL was made with.

Passing char pointers works great though.

Another thing. GetProcAddress() looks for the function specified only. I discovered microsoft does not adhere to it's own @#$#@#$ standards when I made a DLL with BCB. What does this mean? It means you have to be careful, for example

char *Get_GameList(void);
in BCB becomes _Get_GameList as a name but with VC++ it becomes Get_GameList although the BCB name is correct it doesn't work with any emulators because... they are expecting Get_GameList. What I did was wrap the GetProcAddress with a function that looks for both variations.

The best thing to do when using multiple libraries is have classes that wrap each DLL's set of functions and acess them via the classes. That seemed to be the easiest way to do it for me.

Cyb
 
OP
T

tylerbingham

New member
still not working

#include <iostream>
#include <windows.h>

#include "main.h"
#include "dlls\\main.h"
//#pragma comment(lib,"dll1.lib")
//#pragma comment(lib,"dll2.lib")

char str[255];
HINSTANCE lib;

typedef void ( * lpFunc1)(void);

lpFunc1 Func1;

int main(int nNumberofArgs, char* pszArgs[])
{

cout<<"which .dll do you want to load( 1 or 2 )"<< endl << endl;
cin>>str;

if(0 == strcmp ("1",str))
{
lib = LoadLibrary("dlls\\dll1.dll");
if(lib == NULL)
{
cout<<"failed to load .dll"<< endl<< endl;
}

if(lib != NULL)
{
cout<<"loaded .dll"<< endl<< endl;
}

Func1 = (lpFunc1) GetProcAddress(lib, "printMessage");
if (Func1 != NULL)
{
cout<<"loaded procedure :printMessage()";
}
else cout << "Error in procedure address call" << endl<< endl;

//printMessage();
}

if(0 == strcmp ("2",str))
{
//
}

return 0;
}
still not working..........maybe I built the .dll wrong??
 

Cyberman

Moderator
Moderator
Run IMPDEF <DLL NAME> <DLL NAME> on the DLL file and examine the contents of the resulting file.

You must also call FreeLibrary after you are done using the DLL.

Check to be sure the function names are in the DLL you just dumped and you are using the right name for the functions. See my comments about MS versus STANDARD function names :p

Cyb
 
OP
T

tylerbingham

New member
figured it out...kinda

I got the 2 .dll's to load like I wanted, but I have to use a .def file to do it. Any ideas around that?? I am looking to load a .dll the way the emus hosted here do.
 

Cyberman

Moderator
Moderator
Re: figured it out...kinda

tylerbingham said:
I got the 2 .dll's to load like I wanted, but I have to use a .def file to do it. Any ideas around that?? I am looking to load a .dll the way the emus hosted here do.
Hmmm the Def file is just to find out what is in the DLL's and if there function names are exported properly etc.

My Code for DLL dealing:
Code:
//---------------------------------------------------------------------------
char *(*Game)(void);
char *(*Name)(void);
char *(*Author)(void);
void  (*About)(void);
void  (*Edit)(char *);
//---------------------------------------------------------------------------
int DLL_Count(void)
{
   FncCalls[0]++;
   return DLLCount;
}
//---------------------------------------------------------------------------
void *GetFnc(char *Fname)
{
   void * Temp;
   char  Buff[256];

   Temp = GetProcAddress(LibRef, Fname);
   if (Temp == NULL)
   {
      strcpy(Buff, "_");
      strcat(Buff, Fname);
      Temp = GetProcAddress(LibRef, Buff);
   }
   return Temp;
}
//---------------------------------------------------------------------------
bool LoadFncs(void)
{
   bool  Return;
   if (LibRef != NULL)
   {
      Game =   (char * (*)(void))   GetFnc("MemEdit_Game");
      Return = (Game != NULL);
      if (Return)
      {
         Name =   (char * (*)(void))   GetFnc("MemEdit_Name");
         Return = (Name != NULL);
         if (Return)
         {
            Author = (char * (*)(void))   GetFnc("MemEdit_Author");
            Return = (Author != NULL);
            if (Return)
            {
               About =  (void (*)(void))     GetFnc("MemEdit_About");
               Return = (About != NULL);
               if (Return)
               {
                  Edit =   (void (*)(char *))   GetFnc("MemEdit_CardEdit");
                  Return = (Edit != NULL);
               }
            }
         }
      }
   }
   return Return;
}
//---------------------------------------------------------------------------
bool  LoadLib(int GID)
{
   if (LibRef != NULL)
   {
      // unload the prior library
      FreeLibrary(LibRef);
      // null it
      LibRef = NULL;
   }
   if ((GID > 0) && (GID <= GameCount))
   {
      LibRef = LoadLibrary(DllPath[GameIDs[GID - 1].PathDX]);
   }
   if (LibRef != NULL)
   {
      if (!LoadFncs())
      {
         FreeLibrary(LibRef);
         LibRef = NULL;
      }
   }
   return (LibRef != NULL);
}

Granted it's fairly complicated however it has adequate error recovery etc.

I enumerate DLL's this way...

Code:
//---------------------------------------------------------------------------
void Game_Init(void)
{
   char  Path[300];
   char  Dir[256];
   char  Fname[64];
   char  Ext[8];
   char  Where[256];
   char  Plugin[300];
   ffblk FFBLK;
   int Length;
   HINSTANCE   LibRef;
   char *   (*GameID )(void);
   char *PathPtr, *GID;

   FncCalls[7]++;
   for (DLLCount = 0; DLLCount < MAX_DLL; DLLCount++)
   {
      DllPath[DLLCount] = NULL;
   }
   for (DLLCount = 0; DLLCount < MAX_GAMES; DLLCount++)
   {
      GameIDs[DLLCount].ID = NULL;
      GameIDs[DLLCount].PathDX = -1;
   }
   LibRef = NULL;
   DLLCount = 0;
   GameCount = 0;
   Length = GetModuleFileName(NULL, Path, sizeof(Path));
   if (Length)
   {
      _splitpath(Path, Where, Dir, Fname, Ext);
      strcat(Where, Dir);
      strcat(Where, "Plugins\\");
      strcpy(Plugin, Where);
      strcat(Plugin, "*.dll");
      if (findfirst(Plugin, &FFBLK, 0) == 0)//FA_ARCH | FA_RDONLY) == 0)
      {
         PathPtr = DllPathD;
         GID     = GameIDD;
         *PathPtr = 0;
         *GID = 0;
         do
         {
            strcpy(Plugin, Where);
            strcat(Plugin, FFBLK.ff_name);
            LibRef = LoadLibrary(Plugin);
            if (LibRef != NULL)
            {
               GameID = (char *(*)(void))
                  GetFnc("MemEdit_Game");
               if (GameID != NULL)
               {
                  strcpy(PathPtr, Plugin);
                  DllPath[DLLCount] = PathPtr;
                  PathPtr += strlen(PathPtr) + 1;
                  strcpy(GID, GameID());
                  GameIDs[GameCount].ID = GID;
                  GameIDs[GameCount].PathDX = DLLCount;
                  GID += strlen(GID) + 1;
                  DLLCount ++;
                  GameCount ++;
               }
               FreeLibrary(LibRef);
            }
         }
         while(
            (findnext(&FFBLK) == 0) &&
            (DLLCount < MAX_DLL)
            );
      }
   }
   // OK status
   Status = 0;
   // no game selected
   GameSelected = -1;
}

You have to be rather therough and take into account things going wrong and errors that can happen. A common problem I have is the DLL doesn't load properly (sigh) and causes a memory fault.

Cyb
 
OP
T

tylerbingham

New member
hey Cyberman thanx a lot

hey, I finally got it last night!!! I was not exporting the .dll functions correctly. I got my .dll to load and do what it was supposed to do finally after a few hours of hacking through the msdn docs. I have just one more tiny question.....

You know how we use GetProcAddress to get the procedure(i.e. function address)?? is there a way to just search a .dll and find out all of the Procedures it can do without knowing what it's specific function names are?
 

Cyberman

Moderator
Moderator
Re: hey Cyberman thanx a lot

tylerbingham said:
hey, I finally got it last night!!! I was not exporting the .dll functions correctly. I got my .dll to load and do what it was supposed to do finally after a few hours of hacking through the msdn docs. I have just one more tiny question.....

You know how we use GetProcAddress to get the procedure(i.e. function address)?? is there a way to just search a .dll and find out all of the Procedures it can do without knowing what it's specific function names are?
Where there must be a way to do it, however I am not sure how one would do that to be honest. IMPDEF would not be able to give you a list of exported functions otherwise (hmmm). I believe the way to do this might be knowing the format of MS's DLL files and just read through it, I don't think the WinApi supports searching for exported functions in a DLL without an actual name.

Another way to do this would be to call IMPDEF in a shell and directing the output to a file you read after IMPED is done executing.

Cyb
 

N-Rage

New member
theres not much sense in enumerating functions from within a programm, you need information how to call those functions too( arguments and calling conventions ), and that aint stored within a DLL, it simply causes stack corruption if you assume it wrong.
What are you gonna do with functions You dont know anyway? :holiday:

You can however get functionpointers by ordinal numbers, ie get first, second, third, etc exported function of a dll, also by using GetProcAddress(), not using the function name as argument but a special construct( easy using a MACRO ).. cant remember how exactly, but everything is described in the PlatformSDK. You could simply get functionpointers aslong GetProcAddress() aint returning NULL.
 

Cyberman

Moderator
Moderator
N-Rage said:
theres not much sense in enumerating functions from within a programm, you need information how to call those functions too( arguments and calling conventions ), and that aint stored within a DLL, it simply causes stack corruption if you assume it wrong.
What are you gonna do with functions You dont know anyway? :holiday:

You can however get functionpointers by ordinal numbers, ie get first, second, third, etc exported function of a dll, also by using GetProcAddress(), not using the function name as argument but a special construct( easy using a MACRO ).. cant remember how exactly, but everything is described in the PlatformSDK. You could simply get functionpointers aslong GetProcAddress() aint returning NULL.

Actually you just do
Code:
Index = 0;
do
{
   Ptr = GetProceAddress((char *)Index);
   Index++;
}
while (Ptr != NULL);

unfortunately that doesn't get you the function NAMES :p

Cyb
 

N-Rage

New member
Cyberman said:
Actually you just do
Code:
Index = 0;
do
{
   Ptr = GetProceAddress((char *)Index);
   Index++;
}
while (Ptr != NULL);

unfortunately that doesn't get you the function NAMES :p

Cyb

Theres no way to do that in runtime without RAW-parsing the dll... I dont think thats what he wanted anyway... actually i aint having a clue what he wants to do :)
if you have the MS-Compiler you can run dumpbin <dllname> /exports for a list of exported functions.
 

Top