Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Is it possible to have an array of types ?

Is it possible to have an array of types ?

Scheduled Pinned Locked Moved C / C++ / MFC
data-structureshelpquestion
11 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Defenestration
    wrote on last edited by
    #1

    For one of my projects I've created a class wrapper around some functions contained in a DLL. To use these DLL functions, I instantiate an object of the type class wrapper, and then call the member function LoadDLL(). LoadDLL() calls ::LoadLibrary() for the DLL, and then calls GetProcAddress() for each DLL function I wish to wrap. If any of the functions couldn't be found, I wish to FreeLibrary(), and return false. At the moment I do something along the lines of:

    typedef void (*p2DLLFunc1) (void);
    typedef char* (*p2DLLFunc2) (void);

    bool CDLLWrapper::LoadDLL()
    {
    bool bResult = false;

    m\_hmoduleDll = ::LoadLibrary(\_T("DLLName"));
    if (NULL != m\_hmoduleDll)
    { // DLL loaded successfully. Now get addresses of all functions we are supporting
    	m\_funcDLLFunc1	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc1")));
    	m\_funcDLLFunc2	= reinterpret\_cast<p2DLLFunc2>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc2")));
    	m\_funcDLLFunc3	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc3")));
    	
    	if (	NULL != m\_funcDLLFunc1	&&
    		NULL != m\_funcDLLFunc2	&&
    		NULL != m\_funcDLLFunc3)
    	{ // SUCCESS: All wrapped functions found in DLL
    		bResult = true;
    	}
    	else
    	{ // FAILURE: Could not find one or more wrapped functions
    		::FreeLibrary(m\_hmoduleDll);
    	}
    }
    
    return bResult;
    

    }

    However, when lots of functions are being wrapped the above method is a bit tedious and can be error prone. Instead, I would like to do it with a lookup table, like so

    bool CDLLWrapper::LoadDLL()
    {
    struct MyLUT {
    TCHAR* tcFuncName;
    funcDLLFunc;
    int iFunctionSignatureType;
    }; // struct MyLUT {

    static	MyLUT	arrWrappedFuncs\[\]	=	{	\_T("DLLFunc1"),		m\_funcDLLFunc1,	0
    							\_T("DLLFunc2"),		m\_funcDLLFunc2,	1
    							\_T("DLLFunc3"),		m\_funcDLLFunc3,	0
    }; // static	MyLUT	arrWrappedFuncs\[\]
    
    const	int	iNUM\_WRAPPED\_FUNCTIONS	= sizeof(arrWrappedFuncs) / sizeof(MyLUT);
    
    bool	bResult = false;
    
    m\_hmoduleDll = ::LoadLibrary(\_T("DLLName"));
    if (NULL != m\_hmoduleDll)
    { // DLL loaded successfully. Now get addresses of all functions we are supporting
    	bResult = true;	// Assume success
    	for (int i = 0; i < iNUM\_WRAPPED\_FUNCTIONS; ++i)
    	{
    		switch(arrWrappedFuncs\[i\].iFunctionSignatureType)
    		{
    			case 0:
    			{
    				arrWrappedFuncs\[i\].funcDLLFunc	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, arrWrappedFuncs\[i\].tcFuncName));				
    			}
    			break;
    			
    			case 1:
    			{
    
    C D M 3 Replies Last reply
    0
    • D Defenestration

      For one of my projects I've created a class wrapper around some functions contained in a DLL. To use these DLL functions, I instantiate an object of the type class wrapper, and then call the member function LoadDLL(). LoadDLL() calls ::LoadLibrary() for the DLL, and then calls GetProcAddress() for each DLL function I wish to wrap. If any of the functions couldn't be found, I wish to FreeLibrary(), and return false. At the moment I do something along the lines of:

      typedef void (*p2DLLFunc1) (void);
      typedef char* (*p2DLLFunc2) (void);

      bool CDLLWrapper::LoadDLL()
      {
      bool bResult = false;

      m\_hmoduleDll = ::LoadLibrary(\_T("DLLName"));
      if (NULL != m\_hmoduleDll)
      { // DLL loaded successfully. Now get addresses of all functions we are supporting
      	m\_funcDLLFunc1	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc1")));
      	m\_funcDLLFunc2	= reinterpret\_cast<p2DLLFunc2>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc2")));
      	m\_funcDLLFunc3	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc3")));
      	
      	if (	NULL != m\_funcDLLFunc1	&&
      		NULL != m\_funcDLLFunc2	&&
      		NULL != m\_funcDLLFunc3)
      	{ // SUCCESS: All wrapped functions found in DLL
      		bResult = true;
      	}
      	else
      	{ // FAILURE: Could not find one or more wrapped functions
      		::FreeLibrary(m\_hmoduleDll);
      	}
      }
      
      return bResult;
      

      }

      However, when lots of functions are being wrapped the above method is a bit tedious and can be error prone. Instead, I would like to do it with a lookup table, like so

      bool CDLLWrapper::LoadDLL()
      {
      struct MyLUT {
      TCHAR* tcFuncName;
      funcDLLFunc;
      int iFunctionSignatureType;
      }; // struct MyLUT {

      static	MyLUT	arrWrappedFuncs\[\]	=	{	\_T("DLLFunc1"),		m\_funcDLLFunc1,	0
      							\_T("DLLFunc2"),		m\_funcDLLFunc2,	1
      							\_T("DLLFunc3"),		m\_funcDLLFunc3,	0
      }; // static	MyLUT	arrWrappedFuncs\[\]
      
      const	int	iNUM\_WRAPPED\_FUNCTIONS	= sizeof(arrWrappedFuncs) / sizeof(MyLUT);
      
      bool	bResult = false;
      
      m\_hmoduleDll = ::LoadLibrary(\_T("DLLName"));
      if (NULL != m\_hmoduleDll)
      { // DLL loaded successfully. Now get addresses of all functions we are supporting
      	bResult = true;	// Assume success
      	for (int i = 0; i < iNUM\_WRAPPED\_FUNCTIONS; ++i)
      	{
      		switch(arrWrappedFuncs\[i\].iFunctionSignatureType)
      		{
      			case 0:
      			{
      				arrWrappedFuncs\[i\].funcDLLFunc	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, arrWrappedFuncs\[i\].tcFuncName));				
      			}
      			break;
      			
      			case 1:
      			{
      
      C Offline
      C Offline
      Code o mat
      wrote on last edited by
      #2

      Whz do you need reinterpret_cast at the first place? Shouldn't that work without any casting?

      > The problem with computers is that they do what you tell them to do and not what you want them to do. <

      D 1 Reply Last reply
      0
      • C Code o mat

        Whz do you need reinterpret_cast at the first place? Shouldn't that work without any casting?

        > The problem with computers is that they do what you tell them to do and not what you want them to do. <

        D Offline
        D Offline
        Defenestration
        wrote on last edited by
        #3

        Unfortunately not, as you get a compiler error: error C2440: '=' : cannot convert from 'FARPROC' to 'p2DLLFunc1'

        C 1 Reply Last reply
        0
        • D Defenestration

          Unfortunately not, as you get a compiler error: error C2440: '=' : cannot convert from 'FARPROC' to 'p2DLLFunc1'

          C Offline
          C Offline
          Code o mat
          wrote on last edited by
          #4

          Try something like:

          struct	MyLUT {
          TCHAR\*	tcFuncName;
          FARPROC \*funcDLLFunc;
          }; // struct	MyLUT {
          

          static MyLUT arrWrappedFuncs[] = { {_T("DLLFunc1"), (FARPROC *)&m_funcDLLFunc1},
          {_T("DLLFunc2"), (FARPROC *)&m_funcDLLFunc2},
          {_T("DLLFunc3"), (FARPROC *)&m_funcDLLFunc3},
          }; // static MyLUT arrWrappedFuncs[]
          ...
          (*arrWrappedFuncs[i].funcDLLFunc) = GetProcAddress(m_hmoduleDll, arrWrappedFuncs[i].tcFuncName));
          ...

          I just modified your code, so it might not compile, and probably needs adjustment here and there but maybe you get the main idea.

          > The problem with computers is that they do what you tell them to do and not what you want them to do. <

          D 1 Reply Last reply
          0
          • C Code o mat

            Try something like:

            struct	MyLUT {
            TCHAR\*	tcFuncName;
            FARPROC \*funcDLLFunc;
            }; // struct	MyLUT {
            

            static MyLUT arrWrappedFuncs[] = { {_T("DLLFunc1"), (FARPROC *)&m_funcDLLFunc1},
            {_T("DLLFunc2"), (FARPROC *)&m_funcDLLFunc2},
            {_T("DLLFunc3"), (FARPROC *)&m_funcDLLFunc3},
            }; // static MyLUT arrWrappedFuncs[]
            ...
            (*arrWrappedFuncs[i].funcDLLFunc) = GetProcAddress(m_hmoduleDll, arrWrappedFuncs[i].tcFuncName));
            ...

            I just modified your code, so it might not compile, and probably needs adjustment here and there but maybe you get the main idea.

            > The problem with computers is that they do what you tell them to do and not what you want them to do. <

            D Offline
            D Offline
            Defenestration
            wrote on last edited by
            #5

            FARPROC is defined as a function pointer to a function that receives no input, and returns an int (ie. int func(void)). Therefore, this cannot be used for functions whose parameter list and return type are different (eg. char* func1(int)).

            C 1 Reply Last reply
            0
            • D Defenestration

              FARPROC is defined as a function pointer to a function that receives no input, and returns an int (ie. int func(void)). Therefore, this cannot be used for functions whose parameter list and return type are different (eg. char* func1(int)).

              C Offline
              C Offline
              Code o mat
              wrote on last edited by
              #6

              A pointer in itself is just a memory address, what parameters how are passed upon a call is decided where and when you call the function thorough the pointer, but correct me if i am wrong. Just try this:

              void *P1 = (void *)GetProcAddress(DLLHande, "proc_name");
              FARPROC P2 = GetProcAddress(DLLHande, "proc_name");
              pDLLFunc1 P3 = (pDLLFunc1)GetProcAddress(DLLHande, "proc_name");
              pDLLFunc1 P4 = reinterpret_cast(GetProcAddress(DLLHande, "proc_name"));

              And check out the 4 pointer values (for example in the watch window of your debugger if you are using Visual Studio), they all should be the same,

              > The problem with computers is that they do what you tell them to do and not what you want them to do. <

              D 1 Reply Last reply
              0
              • C Code o mat

                A pointer in itself is just a memory address, what parameters how are passed upon a call is decided where and when you call the function thorough the pointer, but correct me if i am wrong. Just try this:

                void *P1 = (void *)GetProcAddress(DLLHande, "proc_name");
                FARPROC P2 = GetProcAddress(DLLHande, "proc_name");
                pDLLFunc1 P3 = (pDLLFunc1)GetProcAddress(DLLHande, "proc_name");
                pDLLFunc1 P4 = reinterpret_cast(GetProcAddress(DLLHande, "proc_name"));

                And check out the 4 pointer values (for example in the watch window of your debugger if you are using Visual Studio), they all should be the same,

                > The problem with computers is that they do what you tell them to do and not what you want them to do. <

                D Offline
                D Offline
                Defenestration
                wrote on last edited by
                #7

                You are correct, and that is the problem. If I don't cast it to the correct type when calling GetProcAddress(), I will have to cast it later on when I call the function pointed to by the pointer. Either way, I will need to cast it at some point. Otherwise I don't think it will let me call it with the relevant parameters and return type. I will have to do some testing to be sure, but my current understanding makes me think it won't work.

                C 1 Reply Last reply
                0
                • D Defenestration

                  You are correct, and that is the problem. If I don't cast it to the correct type when calling GetProcAddress(), I will have to cast it later on when I call the function pointed to by the pointer. Either way, I will need to cast it at some point. Otherwise I don't think it will let me call it with the relevant parameters and return type. I will have to do some testing to be sure, but my current understanding makes me think it won't work.

                  C Offline
                  C Offline
                  Code o mat
                  wrote on last edited by
                  #8

                  How about a different aproach, use a template class, something like this:

                  class CConverterBase
                  {
                  public:
                  virtual operator void =(const FARPROC ptr) = 0;
                  };

                  template
                  class CConverter: public CConverterBase
                  {
                  TFuncPtr &fFuncPtrPtr;
                  public:
                  CConverter(TFuncPtr &ptr):fFuncPtrPtr(ptr) {}

                  operator void =(const FARPROC ptr)
                  {
                  fFuncPtrPtr = (TFuncPtr)ptr;
                  return fFuncPtrPtr;
                  }
                  }

                  And then something like:

                  class Func
                  {
                  TCHAR *pszName;
                  CConverterBase *ptr;
                  };
                  ...
                  Func FuncArr[] = {{_T"DLLFunc1", new CConverter(m_DLLFunc1)}, {_T"DLLFunc2", new CConverter(m_DLLFunc2)}, ...};
                  ...
                  (*FuncAtt[I].ptr) = GetProcAddress(dllhandle, FuncAtt[I].pszName);
                  ...

                  And of course don't forget to free up the objects you instantiated.

                  > The problem with computers is that they do what you tell them to do and not what you want them to do. <

                  D 1 Reply Last reply
                  0
                  • C Code o mat

                    How about a different aproach, use a template class, something like this:

                    class CConverterBase
                    {
                    public:
                    virtual operator void =(const FARPROC ptr) = 0;
                    };

                    template
                    class CConverter: public CConverterBase
                    {
                    TFuncPtr &fFuncPtrPtr;
                    public:
                    CConverter(TFuncPtr &ptr):fFuncPtrPtr(ptr) {}

                    operator void =(const FARPROC ptr)
                    {
                    fFuncPtrPtr = (TFuncPtr)ptr;
                    return fFuncPtrPtr;
                    }
                    }

                    And then something like:

                    class Func
                    {
                    TCHAR *pszName;
                    CConverterBase *ptr;
                    };
                    ...
                    Func FuncArr[] = {{_T"DLLFunc1", new CConverter(m_DLLFunc1)}, {_T"DLLFunc2", new CConverter(m_DLLFunc2)}, ...};
                    ...
                    (*FuncAtt[I].ptr) = GetProcAddress(dllhandle, FuncAtt[I].pszName);
                    ...

                    And of course don't forget to free up the objects you instantiated.

                    > The problem with computers is that they do what you tell them to do and not what you want them to do. <

                    D Offline
                    D Offline
                    Defenestration
                    wrote on last edited by
                    #9

                    I've been thinking a similar thing that I might have to use some C++ features to achieve what I'm after. The idea of a template class is good, but the FuncArr[] can only be initialized with static data (ie. known at compile time). Hmmm, time to put my C++ hat on :)

                    1 Reply Last reply
                    0
                    • D Defenestration

                      For one of my projects I've created a class wrapper around some functions contained in a DLL. To use these DLL functions, I instantiate an object of the type class wrapper, and then call the member function LoadDLL(). LoadDLL() calls ::LoadLibrary() for the DLL, and then calls GetProcAddress() for each DLL function I wish to wrap. If any of the functions couldn't be found, I wish to FreeLibrary(), and return false. At the moment I do something along the lines of:

                      typedef void (*p2DLLFunc1) (void);
                      typedef char* (*p2DLLFunc2) (void);

                      bool CDLLWrapper::LoadDLL()
                      {
                      bool bResult = false;

                      m\_hmoduleDll = ::LoadLibrary(\_T("DLLName"));
                      if (NULL != m\_hmoduleDll)
                      { // DLL loaded successfully. Now get addresses of all functions we are supporting
                      	m\_funcDLLFunc1	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc1")));
                      	m\_funcDLLFunc2	= reinterpret\_cast<p2DLLFunc2>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc2")));
                      	m\_funcDLLFunc3	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc3")));
                      	
                      	if (	NULL != m\_funcDLLFunc1	&&
                      		NULL != m\_funcDLLFunc2	&&
                      		NULL != m\_funcDLLFunc3)
                      	{ // SUCCESS: All wrapped functions found in DLL
                      		bResult = true;
                      	}
                      	else
                      	{ // FAILURE: Could not find one or more wrapped functions
                      		::FreeLibrary(m\_hmoduleDll);
                      	}
                      }
                      
                      return bResult;
                      

                      }

                      However, when lots of functions are being wrapped the above method is a bit tedious and can be error prone. Instead, I would like to do it with a lookup table, like so

                      bool CDLLWrapper::LoadDLL()
                      {
                      struct MyLUT {
                      TCHAR* tcFuncName;
                      funcDLLFunc;
                      int iFunctionSignatureType;
                      }; // struct MyLUT {

                      static	MyLUT	arrWrappedFuncs\[\]	=	{	\_T("DLLFunc1"),		m\_funcDLLFunc1,	0
                      							\_T("DLLFunc2"),		m\_funcDLLFunc2,	1
                      							\_T("DLLFunc3"),		m\_funcDLLFunc3,	0
                      }; // static	MyLUT	arrWrappedFuncs\[\]
                      
                      const	int	iNUM\_WRAPPED\_FUNCTIONS	= sizeof(arrWrappedFuncs) / sizeof(MyLUT);
                      
                      bool	bResult = false;
                      
                      m\_hmoduleDll = ::LoadLibrary(\_T("DLLName"));
                      if (NULL != m\_hmoduleDll)
                      { // DLL loaded successfully. Now get addresses of all functions we are supporting
                      	bResult = true;	// Assume success
                      	for (int i = 0; i < iNUM\_WRAPPED\_FUNCTIONS; ++i)
                      	{
                      		switch(arrWrappedFuncs\[i\].iFunctionSignatureType)
                      		{
                      			case 0:
                      			{
                      				arrWrappedFuncs\[i\].funcDLLFunc	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, arrWrappedFuncs\[i\].tcFuncName));				
                      			}
                      			break;
                      			
                      			case 1:
                      			{
                      
                      D Offline
                      D Offline
                      David Crow
                      wrote on last edited by
                      #10

                      Defenestration wrote:

                      Any ideas ?

                      Have you read this article on dynamic linking?

                      "Love people and use things, not love things and use people." - Unknown

                      "The brick walls are there for a reason...to stop the people who don't want it badly enough." - Randy Pausch

                      1 Reply Last reply
                      0
                      • D Defenestration

                        For one of my projects I've created a class wrapper around some functions contained in a DLL. To use these DLL functions, I instantiate an object of the type class wrapper, and then call the member function LoadDLL(). LoadDLL() calls ::LoadLibrary() for the DLL, and then calls GetProcAddress() for each DLL function I wish to wrap. If any of the functions couldn't be found, I wish to FreeLibrary(), and return false. At the moment I do something along the lines of:

                        typedef void (*p2DLLFunc1) (void);
                        typedef char* (*p2DLLFunc2) (void);

                        bool CDLLWrapper::LoadDLL()
                        {
                        bool bResult = false;

                        m\_hmoduleDll = ::LoadLibrary(\_T("DLLName"));
                        if (NULL != m\_hmoduleDll)
                        { // DLL loaded successfully. Now get addresses of all functions we are supporting
                        	m\_funcDLLFunc1	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc1")));
                        	m\_funcDLLFunc2	= reinterpret\_cast<p2DLLFunc2>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc2")));
                        	m\_funcDLLFunc3	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, \_T("DLLFunc3")));
                        	
                        	if (	NULL != m\_funcDLLFunc1	&&
                        		NULL != m\_funcDLLFunc2	&&
                        		NULL != m\_funcDLLFunc3)
                        	{ // SUCCESS: All wrapped functions found in DLL
                        		bResult = true;
                        	}
                        	else
                        	{ // FAILURE: Could not find one or more wrapped functions
                        		::FreeLibrary(m\_hmoduleDll);
                        	}
                        }
                        
                        return bResult;
                        

                        }

                        However, when lots of functions are being wrapped the above method is a bit tedious and can be error prone. Instead, I would like to do it with a lookup table, like so

                        bool CDLLWrapper::LoadDLL()
                        {
                        struct MyLUT {
                        TCHAR* tcFuncName;
                        funcDLLFunc;
                        int iFunctionSignatureType;
                        }; // struct MyLUT {

                        static	MyLUT	arrWrappedFuncs\[\]	=	{	\_T("DLLFunc1"),		m\_funcDLLFunc1,	0
                        							\_T("DLLFunc2"),		m\_funcDLLFunc2,	1
                        							\_T("DLLFunc3"),		m\_funcDLLFunc3,	0
                        }; // static	MyLUT	arrWrappedFuncs\[\]
                        
                        const	int	iNUM\_WRAPPED\_FUNCTIONS	= sizeof(arrWrappedFuncs) / sizeof(MyLUT);
                        
                        bool	bResult = false;
                        
                        m\_hmoduleDll = ::LoadLibrary(\_T("DLLName"));
                        if (NULL != m\_hmoduleDll)
                        { // DLL loaded successfully. Now get addresses of all functions we are supporting
                        	bResult = true;	// Assume success
                        	for (int i = 0; i < iNUM\_WRAPPED\_FUNCTIONS; ++i)
                        	{
                        		switch(arrWrappedFuncs\[i\].iFunctionSignatureType)
                        		{
                        			case 0:
                        			{
                        				arrWrappedFuncs\[i\].funcDLLFunc	= reinterpret\_cast<p2DLLFunc1>(GetProcAddress(m\_hmoduleDll, arrWrappedFuncs\[i\].tcFuncName));				
                        			}
                        			break;
                        			
                        			case 1:
                        			{
                        
                        M Offline
                        M Offline
                        Michael Dunn
                        wrote on last edited by
                        #11

                        You can use a MS extension in GetProcAddress() calls:

                        (FARPROC&) func_ptr = GetProcAddress ( hModule, "FunctionName" );

                        That way you don't have to make a new typedef for each function pointer.

                        --Mike-- Visual C++ MVP :cool: LINKS~! CP SearchBar v3.0 | C++ Forum FAQ "That's what's great about doing user interface work. No matter what you do, people will say that what you did was idiotic." -- Raymond Chen

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups