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 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