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. Dlls, callbacks and function pointers

Dlls, callbacks and function pointers

Scheduled Pinned Locked Moved C / C++ / MFC
helpc++performancetutorialquestion
9 Posts 4 Posters 3 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.
  • I Offline
    I Offline
    Irenepower
    wrote on last edited by
    #1

    :wtf: Hi, I've got this problem when developing my first DLL: I have a DLL with an Interface class. I also have an application that calls some functions from the Interface class. In the application there exist a function that I want to be called from the DLL (as a callback), so I pass a function pointer to the DLL. I want to store the function pointer inside the DLL so I can call the function whenever I want, for this reason I have created an struct in which I store the function pointer and some other things. Until here, everything fine... The problem comes when doing an instance of the struct; if I do that instance inside the Interface class (as a member) I cannot copy the function pointer in it; but if I do the instance outside any class (that is as "global") then there is no problem when copying the functon pointer. Does anybody knows why can this happen?, it can be a problem of memory access? Here is a "meta-language" example: DLL: In Interface.h: typedef struct { functionpointer }MyStruct; class Interface { Interface (); MyStruct mystruct; void FillStruct (function_pointer_from_outside); //this is the exported function } In Interface.cpp void Interface::FillStruct(function_pointer_from_outside) { mystruct.functionpointer = function_pointer_from_outside; //THIS GIVES EXECUTION PROBLEM } On the other hand if I make something like this, it works: In Interface.h: typedef struct { functionpointer }MyStruct; class Interface { Interface (); void FillStruct (function_pointer_from_outside); } In Interface.cpp MyStruct mystruct; //Instance as "global"!!!!! void Interface::FillStruct(function_pointer_from_outside) { mystruct.functionpointer = function_pointer_from_outside; //OK!!! } HELP!!

    A 1 Reply Last reply
    0
    • I Irenepower

      :wtf: Hi, I've got this problem when developing my first DLL: I have a DLL with an Interface class. I also have an application that calls some functions from the Interface class. In the application there exist a function that I want to be called from the DLL (as a callback), so I pass a function pointer to the DLL. I want to store the function pointer inside the DLL so I can call the function whenever I want, for this reason I have created an struct in which I store the function pointer and some other things. Until here, everything fine... The problem comes when doing an instance of the struct; if I do that instance inside the Interface class (as a member) I cannot copy the function pointer in it; but if I do the instance outside any class (that is as "global") then there is no problem when copying the functon pointer. Does anybody knows why can this happen?, it can be a problem of memory access? Here is a "meta-language" example: DLL: In Interface.h: typedef struct { functionpointer }MyStruct; class Interface { Interface (); MyStruct mystruct; void FillStruct (function_pointer_from_outside); //this is the exported function } In Interface.cpp void Interface::FillStruct(function_pointer_from_outside) { mystruct.functionpointer = function_pointer_from_outside; //THIS GIVES EXECUTION PROBLEM } On the other hand if I make something like this, it works: In Interface.h: typedef struct { functionpointer }MyStruct; class Interface { Interface (); void FillStruct (function_pointer_from_outside); } In Interface.cpp MyStruct mystruct; //Instance as "global"!!!!! void Interface::FillStruct(function_pointer_from_outside) { mystruct.functionpointer = function_pointer_from_outside; //OK!!! } HELP!!

      A Offline
      A Offline
      Antti Keskinen
      wrote on last edited by
      #2

      My first question would be, what is the error during execution ? A run-time error ? An exception ? An access violation ? Finding out the error type is integral to determining what the cause of the error is. I believe it to be an access violation, though. As a suggestion, you should try defining the function pointer as a standard pointer-to-function type. You shouldn't encapsulate it into a struct (what is the reason behind this, by the way ?) Another working way could be to call GetModuleHandle on the main application. This returns a handle to the executable used to start the process. In english, it is the starting address of your main application. Now, if you pass this module handle into the DLL, you can use GetProcAddress inside the DLL code to query for the address of the function in the main module. This is something of a reverse-usage of the most common case: querying for a function address inside a DLL. Instead, we query for a function address inside the main application. The returned value can then be used to invoke the function in the main application module. Using GetProcAddress ensures that the memory location pointed to by the returned pointer is ensured to contain information of to what module's memory area it points to. This may not be the case if you just pass the pointer using address-of operator. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.

      U 1 Reply Last reply
      0
      • A Antti Keskinen

        My first question would be, what is the error during execution ? A run-time error ? An exception ? An access violation ? Finding out the error type is integral to determining what the cause of the error is. I believe it to be an access violation, though. As a suggestion, you should try defining the function pointer as a standard pointer-to-function type. You shouldn't encapsulate it into a struct (what is the reason behind this, by the way ?) Another working way could be to call GetModuleHandle on the main application. This returns a handle to the executable used to start the process. In english, it is the starting address of your main application. Now, if you pass this module handle into the DLL, you can use GetProcAddress inside the DLL code to query for the address of the function in the main module. This is something of a reverse-usage of the most common case: querying for a function address inside a DLL. Instead, we query for a function address inside the main application. The returned value can then be used to invoke the function in the main application module. Using GetProcAddress ensures that the memory location pointed to by the returned pointer is ensured to contain information of to what module's memory area it points to. This may not be the case if you just pass the pointer using address-of operator. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.

        U Offline
        U Offline
        User 1248880
        wrote on last edited by
        #3

        It is an exception error; a windows called "Just-In-Time Debugging" appear saying: "An exception 'System.NullReferenceException' has occurred in testUI.exe". Here is the definition of the pointer in the application (testUI.exe); as you can see, it is a pointer to a member function: typedef void (CListener::*ListPtr)(); ListPtr pListPtr = new ListPtr; pListPtr = &CListener::MyFunction; I use a struct in the DLL because I want to store the pointer to the function, the pointer to the CListener class created in the textUI.exe, and an integer that acts as an identifier. Furthermore, I want to create an array of this struct, because I want the DLL to be capable to work with more that one textUI.exe at the same time (each one of them has its own version of "MyFunction"), and I want to store independently a reference to every function of each CListener object of each textUI.exe. Thanks for your help Irene

        A 1 Reply Last reply
        0
        • U User 1248880

          It is an exception error; a windows called "Just-In-Time Debugging" appear saying: "An exception 'System.NullReferenceException' has occurred in testUI.exe". Here is the definition of the pointer in the application (testUI.exe); as you can see, it is a pointer to a member function: typedef void (CListener::*ListPtr)(); ListPtr pListPtr = new ListPtr; pListPtr = &CListener::MyFunction; I use a struct in the DLL because I want to store the pointer to the function, the pointer to the CListener class created in the textUI.exe, and an integer that acts as an identifier. Furthermore, I want to create an array of this struct, because I want the DLL to be capable to work with more that one textUI.exe at the same time (each one of them has its own version of "MyFunction"), and I want to store independently a reference to every function of each CListener object of each textUI.exe. Thanks for your help Irene

          A Offline
          A Offline
          Antti Keskinen
          wrote on last edited by
          #4

          Humm.. It seems here that each textUI.exe executable creates a new object of the CListener class ? Is this correct ? So, could there be a reason why you wouldn't just pass around a pointer to the object itself ? Like, the executable that loads the DLL provides a function that will return the address of the local CListener object ? If the DLL is aware of the declaration of CListener, you can use the returned address as a standard pointer-to-class to call the member functions. This way, you wouldn't need a pointer to the member function, but would have a pointer to the entire class. The pointer's size wouldn't change much, so the memory requirements would be held in check. Naturally, this approach would place more strict design issues on the DLL code, especially if different functions of the class need to be called at different times. Perhaps you should increase the struct so that in addition to the pointer and the reference number, it would contain a flag that specifies the function to call ? -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.

          U 1 Reply Last reply
          0
          • A Antti Keskinen

            Humm.. It seems here that each textUI.exe executable creates a new object of the CListener class ? Is this correct ? So, could there be a reason why you wouldn't just pass around a pointer to the object itself ? Like, the executable that loads the DLL provides a function that will return the address of the local CListener object ? If the DLL is aware of the declaration of CListener, you can use the returned address as a standard pointer-to-class to call the member functions. This way, you wouldn't need a pointer to the member function, but would have a pointer to the entire class. The pointer's size wouldn't change much, so the memory requirements would be held in check. Naturally, this approach would place more strict design issues on the DLL code, especially if different functions of the class need to be called at different times. Perhaps you should increase the struct so that in addition to the pointer and the reference number, it would contain a flag that specifies the function to call ? -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.

            U Offline
            U Offline
            User 1248880
            wrote on last edited by
            #5

            Yes, that is right, each textUI.exe creates a new object of CListener; the I create a pointer to the object: pListener. At the beginning I tryed just to pass the pointer to the DLL, and to execute the function like this: pListener->MyFunction(); but as CListener is also defined inside the DLL and an object instanstiated; instead of executing the MyFunction from the object outside the DLL, it was the MyFunction from the object inside the DLL the one that was executed... Strange, I know. I read information in Internet, and I saw that always when you want to call a function from a DLL (and this function is outside the DLL), it was necessary to pass the pointer to the function. I did that and it worked, but with the constraint that I mention in the first post...

            A 1 Reply Last reply
            0
            • U User 1248880

              Yes, that is right, each textUI.exe creates a new object of CListener; the I create a pointer to the object: pListener. At the beginning I tryed just to pass the pointer to the DLL, and to execute the function like this: pListener->MyFunction(); but as CListener is also defined inside the DLL and an object instanstiated; instead of executing the MyFunction from the object outside the DLL, it was the MyFunction from the object inside the DLL the one that was executed... Strange, I know. I read information in Internet, and I saw that always when you want to call a function from a DLL (and this function is outside the DLL), it was necessary to pass the pointer to the function. I did that and it worked, but with the constraint that I mention in the first post...

              A Offline
              A Offline
              Antti Keskinen
              wrote on last edited by
              #6

              IrenePwr wrote: - but as CListener is also defined inside the DLL and an object instanstiated; instead of executing the MyFunction from the object outside the DLL, it was the MyFunction from the object inside the DLL the one that was executed... Strange, I know. This is correct. The DLL has it's own memory space, and the run-time interpreted the pointer you passed. Because a similar object was found in this local space, the run-time thought that it must be this one. I also doubt that you did not use GetProcAddress to get either the address or the function to return the address. Try doing it so that you export a function from the main module, and use GetProcAddress to get this function. The function just returns the address of the local CListener object. This ensures that the function executes in the address space of the main module, and thus the address returned points into the main module's memory area instead of the DLL's. One more option would be to try to use __declspec(dllexport) on the class in the main module. This WILL limit the number of the objects instantated to a single one, because you can't export multiple objects with same signatures. This wouldn't be safe. Then using __declspec(dllimport) to create a pointer-to-class in the DLL, and it "should" discover the correct class, as it looks for it across the DLL boundaries. Greatest problems arise due to the CListener class found inside the DLL. Could it be a viable option to create a copy of CListener class and rename it as CDLLListener, for example ? This would change the signatures of the objects, and might thus allow us to use the pointers you mentioned without the danger that it'd point to the local object instead of the remote one. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.

              A 1 Reply Last reply
              0
              • A Antti Keskinen

                IrenePwr wrote: - but as CListener is also defined inside the DLL and an object instanstiated; instead of executing the MyFunction from the object outside the DLL, it was the MyFunction from the object inside the DLL the one that was executed... Strange, I know. This is correct. The DLL has it's own memory space, and the run-time interpreted the pointer you passed. Because a similar object was found in this local space, the run-time thought that it must be this one. I also doubt that you did not use GetProcAddress to get either the address or the function to return the address. Try doing it so that you export a function from the main module, and use GetProcAddress to get this function. The function just returns the address of the local CListener object. This ensures that the function executes in the address space of the main module, and thus the address returned points into the main module's memory area instead of the DLL's. One more option would be to try to use __declspec(dllexport) on the class in the main module. This WILL limit the number of the objects instantated to a single one, because you can't export multiple objects with same signatures. This wouldn't be safe. Then using __declspec(dllimport) to create a pointer-to-class in the DLL, and it "should" discover the correct class, as it looks for it across the DLL boundaries. Greatest problems arise due to the CListener class found inside the DLL. Could it be a viable option to create a copy of CListener class and rename it as CDLLListener, for example ? This would change the signatures of the objects, and might thus allow us to use the pointers you mentioned without the danger that it'd point to the local object instead of the remote one. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.

                A Offline
                A Offline
                Antti Keskinen
                wrote on last edited by
                #7

                This getting interestingly strange. I did a few prelimenary checks of my own, and found out that if your main executable module and the DLL have similar objects declared, then using GetProcAddress will fail, if the methods of the classes are not declared as virtual. I had a class called CMyDLLClass, and the same header file was contained in the DLL as well. Now, both the main module and the DLL created objects of this type. When the methods of the class were all declared as virtual, the run-time interpreted the pointers correctly. If they were not virtual, then calling the members through the pointer in the main module ALWAYS called the methods of the object declared in the main module's context, regardless of which pointer I used. More interestingly, the pointers pointed to different locations in memory as well... This starts to feel like a bug in the compiler or the optimizations it uses. Not sure yet, though.. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.

                U L 2 Replies Last reply
                0
                • A Antti Keskinen

                  This getting interestingly strange. I did a few prelimenary checks of my own, and found out that if your main executable module and the DLL have similar objects declared, then using GetProcAddress will fail, if the methods of the classes are not declared as virtual. I had a class called CMyDLLClass, and the same header file was contained in the DLL as well. Now, both the main module and the DLL created objects of this type. When the methods of the class were all declared as virtual, the run-time interpreted the pointers correctly. If they were not virtual, then calling the members through the pointer in the main module ALWAYS called the methods of the object declared in the main module's context, regardless of which pointer I used. More interestingly, the pointers pointed to different locations in memory as well... This starts to feel like a bug in the compiler or the optimizations it uses. Not sure yet, though.. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.

                  U Offline
                  U Offline
                  User 1248880
                  wrote on last edited by
                  #8

                  Whow!! That can be what happens in my project also... I don“t have the functions in the header file inside the DLL declared as virtual. I will check it tomorrow and I'll let you know... Now I don't have the project in front of me anymore (it is at work :)) Thanks for your help and interest Irene

                  1 Reply Last reply
                  0
                  • A Antti Keskinen

                    This getting interestingly strange. I did a few prelimenary checks of my own, and found out that if your main executable module and the DLL have similar objects declared, then using GetProcAddress will fail, if the methods of the classes are not declared as virtual. I had a class called CMyDLLClass, and the same header file was contained in the DLL as well. Now, both the main module and the DLL created objects of this type. When the methods of the class were all declared as virtual, the run-time interpreted the pointers correctly. If they were not virtual, then calling the members through the pointer in the main module ALWAYS called the methods of the object declared in the main module's context, regardless of which pointer I used. More interestingly, the pointers pointed to different locations in memory as well... This starts to feel like a bug in the compiler or the optimizations it uses. Not sure yet, though.. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.

                    L Offline
                    L Offline
                    Lost User
                    wrote on last edited by
                    #9

                    Hi, Yes, it was that. If I define my functions inside the DLL as virtual, then the run-time interprets the pointers correctly. Anyway, I find the same problem as before... just try to store the pointer of your class CMyDLLClass that you pass to your DLL, in a variable that is declared inside another class from your DLL... I cannot do that. I can only store the pointer if the variable is declared globally (outside any class)... In any case, the code looks much better now, though... Irene

                    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