bugGNUstep - Bugs: bug #32383, NSClassFromString returns nil on...

Group
 
 

bug #32383: NSClassFromString returns nil on MinGw if the string class is in a shared library and hasn't yet been used

Submitter:  Brock Erwin <berwin>
Submitted:  Mon 07 Feb 2011 10:36:46 PM UTC
   
 
Category:  Base/Foundation Severity:  3 - Normal
Item Group:  Bug Status:  Invalid
Privacy:  Public Assigned to:  None
Open/Closed:  Declined
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Wed 09 Feb 2011 11:15:52 PM UTC, comment #7: 


> -- is this what you are referring to in order
> to get the class loaded?


Yes and no.  Obviously referring to the class by name to get it
loaded kind of defeats the purpose of NSClassFromString() ;-)

I was referring to a standard trick that is used by
GNUstep programs on Windows to get DLLs to load correctly, which
refers to the entire DLL, not single classes.  I'm not sure
it would work in this case, though, I'd suggest you try.

For example, here is a copy&paste from the Renaissance (a GNUstep library) manual that explains the trick in that
context --

----------

"2.5.2 A small tweak to get it to work on Microsoft Windows

If you are only using the NSBundle Additions API, you can have a problem on Microsoft Windows where you need to reference something inside a library to get it linked in. The recommended workaround is to add the following line (or a similar one) to your program (typically in your main.m file):

int (linkRenaissanceIn)(int, const char *) = GSMarkupApplicationMain;

This defines a (dummy) function pointer called linkRenaissanceInt, and generates a reference to GSMarkupApplicationMain which fixes the problem."

-------

You could try doing something similar.  Identify a public
function in your DLL (or create a dummy one if missing).

Then, in your program, add a variable somewhere which is a
function pointer, and initialize it with the function in the
DLL.  That references a symbol inside the DLL, and should cause
it to be loaded.

Does it help with your problem ?


> and i've always assumed that NSClassFromString would work
> at any time after the +load method (if it is implemented)
> had, or would have been called.


Yes, that is correct.  Brock's problem is that unless you drag
the class in somehow (by referencing it explicitly in your
source code, which IIRC causes the compiler to emit
a reference to the class), the class is not loaded, and the +load
method is not called.  Hence, when you call NSClassFromString(),
the class is not returned because it has not been loaded yet. :-(

Thanks

Nicola Pero <nico>
Group Member
Wed 09 Feb 2011 03:34:48 AM UTC, comment #6: 

-- is this what you are referring to in order to get the class loaded?

what I meant was being loaded was the class having the +load method called, this at least has well defined semantics of before main or after a dlopen, see

http://www.mikeash.com/pyblog/friday-qa-2009-05-22-objective-c-class-loading-and-initialization.html

http://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/clm/NSObject/load

and i've always assumed that NSClassFromString would work at any time after the +load method (if it is implemented) had, or would have been called.

matt rice <ratmice>
Group Member
Tue 08 Feb 2011 06:31:18 PM UTC, comment #5: 

Hmm, I'm actually inclined to wonder if neither windows nor linux is correct.

Wouldn't the ideal situation be ... if the linker didn't load all classes (like mingw), but the objc runtime function did check any shared libraries in use, and load classes on demand?  We wouldn't load any code we didn't need, but we would have all the stuff from disk available if we do need it.

I've no idea how to achieve that though.

Richard Frith-Macdonald <CaS>
Group Member
Tue 08 Feb 2011 05:34:52 PM UTC, comment #4: 

Richard:

I have attached a new tarball with a GNUmakefile which I believe should compile on your system.

Matt & Nicola:

I agree that this definitely sounds like a problem with the compiler/linker and not a bug in NSClassFromString.  As you point out and as I noticed as well on my GNU/Linux/Ubuntu system, it seems as though the compiler/linker loads all classes from shared libraries by default, but on windows this does not seem to be the case (for DLLs).

Nicola wrote:
"Anyhow, Brock,
making sure all symbols in DLLs are loaded is a typical
Windows problem. Have you tried referencing symbols in the DLL
in your program to make sure it is loaded up ? Eg, some people
add a global function pointer variable to their program, and
initialize it by pointing it to a function in the DLL they are
loading, to make sure the DLL is loaded when the program starts
up."

If you look at the file 'test.m' which I attached on line 14:

 13     // UNCOMMENT the following line, and you will see the bug dissappear...
 14     foo = [MYClass class];

-- is this what you are referring to in order to get the class loaded?

Brock Erwin <berwin>
Tue 08 Feb 2011 12:59:46 PM UTC, comment #3: 

I'm curious if the executable is containing a mixture of dll's and static libraries (like a static libobjc), and if the objc_load_callback is being called, or the classes +load method (i'd guess not), and if so does using a dll version of whatever static library change this,

I had previously appeared to have issues which sound similar of the shared library constructor not being called when it was linked with a static library, but it was difficult to tell as I wasn't having any luck setting breakpoints or doing any logging before main, and am in general unfamiliar with the platform.

anyhow, as Nicola says its a problem with the compiler/linker and i'd add in and/or runtime library

matt rice <ratmice>
Group Member
Mon 07 Feb 2011 11:57:52 PM UTC, comment #2: 

It certainly isn't a bug in NSClassFromString(), but I do wonder
if it is a bug in the compiler/linker or not. :-(

On my GNU/Linux, the example works; the class is loaded
and available automatically even when not explicitly referenced.

So the compiler/linker seem to be behaving differently on
GNU/Linux and Windows, which suggests one of the two may
need to be changed.

On GNU/Linux it seems that the compiler/linker make sure that
all classes from the shared libraries that you link are loaded
in automatically.  This is great, but it is not efficient.
Presumably classes should only be loaded when/if they are
referenced ?  Does it really matter ?

If we like the existing GNU/Linux behaviour, maybe we
should look at how we make sure that it works on the same way on
MinGW.

--

Anyhow, Brock,

making sure all symbols in DLLs are loaded is a typical
Windows problem.  Have you tried referencing symbols in the DLL
in your program to make sure it is loaded up ?  Eg, some people
add a global function pointer variable to their program, and
initialize it by pointing it to a function in the DLL they are
loading, to make sure the DLL is loaded when the program starts
up.

Let me know if you have any luck with such a workaround. ;-)

Thanks

Nicola Pero <nico>
Group Member
Mon 07 Feb 2011 11:06:44 PM UTC, comment #1: 

1. The behavior you describe seems to be correct (ie not a bug), NSClassFromString() is not supposed to return a non-existent class ... you have to have loaded the class in some way before it can be found.  Calling a method of the class and linking the library will of course get the linker to load the class at program startup, which is why NSClassFromString() is able to return the named class in the version of the program where you have called [RandomClass class].

2. Your example won't compile on my system because you haven't used gnustep-make. I suggest looking at http://www.gnustep.it/nicola/Tutorials/WritingMakefiles/index.html
so that you can write a makefile which will work on any system.

Richard Frith-Macdonald <CaS>
Group Member
Mon 07 Feb 2011 10:36:46 PM UTC, original submission:  

This bug only manifests itself on a GNUstep MinGW windows installation.  I am testing on a Windows 7 system, and I installed GNUstep MSYS System, GNUstep Core, and GNUstep Devel from http://www.gnustep.org/experience/Windows.html.

Here's the problem:

NSClassFromString(@"RandomClass") returns nil if "RandomClass" resides in a Dynamically Linked Library (DLL), AND "RandomClass" has not yet been used.  If however I make a call like this:

Class foo = [RandomClass class];

right before I make my NSClassFromString(@"RandomClass") call then I no longer notice the bug.  I have created a quick example code with a Makefile that is attached, so just untar the code and try it out to verify this is not working.

Brock Erwin <berwin>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #22626:  nsclassfromstring-GNUmakefile.tar.gz added by berwin (1KiB - application/x-gzip - Richard: I have attached a new tarball with a GNUmakefile which I believe should compile on your system.)
file #22619:  nsclassfromstring.tar.gz added by berwin (951B - application/x-gzip)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by ratmice (Posted a comment)
  • -email is unavailable- added by nico (Posted a comment)
  • -email is unavailable- added by CaS (Posted a comment)
  • -email is unavailable- added by berwin (Submitted the item)
  • -email is unavailable- added by berwin
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follow 5 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2011-02-08 berwin Attached File- Added nsclassfromstring-GNUmakefile.tar.gz, #22626
    2011-02-07 CaS StatusNone Invalid
        Open/ClosedOpen Declined
    2011-02-07 berwin Attached File- Added nsclassfromstring.tar.gz, #22619
        Carbon-Copy- Added -email is unavailable-

    Back to the top

    Powered by Savane 3.13-02a9.
    Corresponding source code