CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Exporting a struct from a DLL

    I'm trying to build the gtkmm library using MSVC. One of its source files declares a struct called BuiltinStockID together with some objects of that type - e.g.

    Code:
    // In the header file:-
    namespace Gtk
    {
    	struct BuiltinStockID
    	{
    		const char* id;
    	};
    
    	namespace Stock
    	{
    		extern GTKMM_API const Gtk::BuiltinStockID APPLY;  /* @image gtk-apply.png  */
    		extern GTKMM_API const Gtk::BuiltinStockID CANCEL; /* @image gtk-cancel.png */
    		extern GTKMM_API const Gtk::BuiltinStockID OK;     /* @image gtk-ok.png     */
    	}
    }
    GTKMM_API is obviously _declspec(dllimport) (or export) as appropriate. It seems a bit unusual to use extern in addition GTKMM_API but the code won't compile if I try to exclude it. The actual instantiations are in one of the library's source files- e.g.

    Code:
    // In a source file
    const Gtk::BuiltinStockID APPLY  = { GTK_STOCK_APPLY };
    const Gtk::BuiltinStockID CANCEL = { GTK_STOCK_CANCEL };
    const Gtk::BuiltinStockID OK     = { GTK_STOCK_OK };
    GTK_STOCK_APPLY etc are simple strings such as "gtk-apply". They mostly refer to image files for the library to load (in this case, for dialog button images) although that's probably not relevant to the problem.

    If I run dumpbin /EXPORTS on the built DLL it does seem to have some exported symbols with the names Gtk::Stock::APPLY, Gtk::Stock::CANCEL, Gtk::Stock::OK etc. However, if I write this in one of my own source files:-

    Code:
    Gtk::BuiltinStockID MyStockID;
    MyStockID = Gtk::Stock::CANCEL;  //  <--- debugger reports <Bad Ptr>
    You can see that the Gtk::Stock::CANCEL object is invalid (my debugger reports it as a bad pointer). Likewise, if I try to pass Gtk::Stock::CANCEL as a parameter to a function. What's going wrong
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  2. #2
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Exporting a struct from a DLL

    Is the actual instantiation code in one of the library's source files ever executed? If it is, does the debugger report that the values correct? When does the debugger report that they go bad?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #3
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: Exporting a struct from a DLL

    If I place a break point on that line I indicated, the debugger says <Bad Ptr> as soon as it stops there. If I press F10 to step on, it doesn't actually crash but I don't get a valid object either. I've got a feeling that the <Bad Ptr> message refers to the struct's 'id' field. The constants GTK_STOCK_APPLY / GTK_STOCK_CANCEL etc are simple #defines:-

    Code:
    #define GTK_STOCK_APPLY  "gtk-apply"
    #define GTK_STOCK_CANCEL "gtk-cancel"
    #define GTK_STOCK_OK     "gtk-ok"
    I'm not yet sure if that's contributing to the problem somehow. Regarding instantiation, it's exactly as I described with these lines:-

    Code:
    // In a source file
    const Gtk::BuiltinStockID APPLY  = { GTK_STOCK_APPLY };
    const Gtk::BuiltinStockID CANCEL = { GTK_STOCK_CANCEL };
    const Gtk::BuiltinStockID OK     = { GTK_STOCK_OK };
    There's a whole bunch of such lines at the top of one of the library's source files. Nothing (within the library itself) seems to use any of the instantiated objects.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  4. #4
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Exporting a struct from a DLL

    Quote Originally Posted by John E View Post
    GTKMM_API is obviously _declspec(dllimport) (or export) as appropriate. It seems a bit unusual to use extern in addition GTKMM_API but the code won't compile if I try to exclude it. The actual instantiations are in one of the library's source files- e.g.
    That's because these are variable declarations, not function declarations. If you omit the extern keyword, the variables are defined in any cpp file that includes this header, which will cause linker errors when included in more than one cpp file.

    Regarding the <Bad Ptr> reported by the debugger, maybe that's just the debugger screwing up. Try to copy the value to a std::string and see what the value of the string is.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  5. #5
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: Exporting a struct from a DLL

    Quote Originally Posted by D_Drmmr View Post
    Regarding the <Bad Ptr> reported by the debugger, maybe that's just the debugger screwing up. Try to copy the value to a std::string and see what the value of the string is.
    Good suggestion but in fact that proved that the pointer address is indeed invalid (the program crashed when trying to assign whatever it's pointing to to a std::string).

    Here's a theory... when the DLL was first linked, the value in (each) instance of BultinStockID::id would presumably have been set to the address of an appropriate string literal somewhere within the DLL. Is there any reason why BuiltinStockID::id would need to get changed / updated at run time? (cos presumably nothing's updating it??)

    2nd theory... when the DLL gets loaded at run time, presumably something needs to initialise the addresses of any exported symbols. What if each structure is getting exported but not its 'id' member? It seems unlikely but is that possible?
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  6. #6
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Exporting a struct from a DLL

    Quote Originally Posted by John E View Post
    If I place a break point on that line I indicated, the debugger says <Bad Ptr> as soon as it stops there. If I press F10 to step on, it doesn't actually crash but I don't get a valid object either. I've got a feeling that the <Bad Ptr> message refers to the struct's 'id' field. The constants GTK_STOCK_APPLY / GTK_STOCK_CANCEL etc are simple #defines:-

    Code:
    #define GTK_STOCK_APPLY  "gtk-apply"
    #define GTK_STOCK_CANCEL "gtk-cancel"
    #define GTK_STOCK_OK     "gtk-ok"
    I'm not yet sure if that's contributing to the problem somehow. Regarding instantiation, it's exactly as I described with these lines:-

    Code:
    // In a source file
    const Gtk::BuiltinStockID APPLY  = { GTK_STOCK_APPLY };
    const Gtk::BuiltinStockID CANCEL = { GTK_STOCK_CANCEL };
    const Gtk::BuiltinStockID OK     = { GTK_STOCK_OK };
    There's a whole bunch of such lines at the top of one of the library's source files. Nothing (within the library itself) seems to use any of the instantiated objects.
    Yes, but this is using the debugger on your code and finding that the pointer is bad. My idea was to use the debugger on the library code and check that the lines
    Code:
    const Gtk::BuiltinStockID APPLY  = { GTK_STOCK_APPLY };
    etc are actually being executed within the library and if they are then to check within the libray code to make sure they are valid and then to trace through the library to fnd when the pointers become invalid. Is this instantiation code part of dllmain or some other initialisation routine? What causes these lines to be executed and when?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  7. #7
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Exporting a struct from a DLL

    Third theory is that you forgot to put struct definitions to proper namespace, so there was nothing to export.

    Code:
    #include "98dll.h"
    
    #define GTK_STOCK_APPLY  "gtk-apply"
    #define GTK_STOCK_CANCEL "gtk-cancel"
    #define GTK_STOCK_OK     "gtk-ok"
    
    namespace Gtk { namespace Stock {
    
    const Gtk::BuiltinStockID APPLY  = { GTK_STOCK_APPLY };
    const Gtk::BuiltinStockID CANCEL = { GTK_STOCK_CANCEL };
    const Gtk::BuiltinStockID OK     = { GTK_STOCK_OK };
    
    }}
    I always check if everything exported as expected. Please see the sample.
    Attached Files Attached Files
    Last edited by Igor Vartanov; November 8th, 2013 at 12:15 PM.
    Best regards,
    Igor

  8. #8
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: Exporting a struct from a DLL

    Quote Originally Posted by Igor Vartanov View Post
    Third theory is that you forgot to put struct definitions to proper namespace, so there was nothing to export.
    Oops... I forgot to show the namespaces in my example but in fact they are in the actual code

    I built your sample Igor which is essentially identical to the original library code and it worked exactly as expected. I guess I'll need to look at the original VC project to see if there's some setting that's preventing it from working
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  9. #9
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Exporting a struct from a DLL

    Quote Originally Posted by John E View Post
    I forgot to show the namespaces in my example but in fact they are in the actual code
    Then I can think only of one scenario that your library appears unloaded somehow to the moment of referencing.
    Best regards,
    Igor

  10. #10
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: Exporting a struct from a DLL

    Quote Originally Posted by Igor Vartanov View Post
    Then I can think only of one scenario that your library appears unloaded somehow to the moment of referencing.
    A good theory - but some of the library's functions have already been called by the time this bit's needed.

    There are A LOT of exported symbols in this DLL (over 13,000). Could that be exceeding some internal limit? The DLL itself isn't massive - just over 3.3Mb (Mb, not Gb) so that shouldn't be a factor...
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  11. #11
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Exporting a struct from a DLL

    I don't think this is a limit issue. If it were, you would never had it be successfully built. As for the other functions already called, that means nothing, as the library can be unloaded any moment later. Though this could be easily checked with VS, just put a breakpoint and inspect modules list.
    Best regards,
    Igor

  12. #12
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    Re: Exporting a struct from a DLL

    Quote Originally Posted by John E View Post
    I built your sample Igor [...] and it worked exactly as expected. I guess I'll need to look at the original VC project to see if there's some setting that's preventing it from working
    Arrrrrgh! Yes, it was a setting in the project (well, kinda). One of gtkmm's header files contains a flag which you set if you're building as a static library. When I first built gtkmm (about 3 years ago) I did indeed build it statically. I only converted it to a DLL a few weeks ago. But I'd totally forgotten about that flag (which was still #defined to 1). Now that I've set it correctly, everything works!! It's a bit weird really because everything compiled and linked and I could even call functions in the DLL - but it seems as if the static data objects just weren't getting initialised.

    Thanks for all your suggestions guys - and especially for your sample code Igor. It was only when I saw your code working that it then occurred to me to suspect my project settings.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  13. #13
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Exporting a struct from a DLL

    Quote Originally Posted by John E View Post
    Arrrrrgh! Yes, it was a setting in the project (well, kinda). One of gtkmm's header files contains a flag which you set if you're building as a static library. When I first built gtkmm (about 3 years ago) I did indeed build it statically. I only converted it to a DLL a few weeks ago. But I'd totally forgotten about that flag (which was still #defined to 1). Now that I've set it correctly, everything works!!
    In general, whenever you get a single set of source files and those source files build both static library and DLL's, a preprocessor switch or switches must be set somewhere to build either the static library or DLL.

    In addition, you should create two configurations, one for a DLL build and one for static lib build, where each configuration sets the appropriate switches.

    Regards,

    Paul McKenzie

  14. #14
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Exporting a struct from a DLL

    Quote Originally Posted by John E View Post
    Thanks for all your suggestions guys - and especially for your sample code Igor.
    Well, in fact it was your sample code. I just put all the pieces together and made sure it really works. You might do the same thing any time before.
    Best regards,
    Igor

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured