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

 
 

You are not allowed to post comments on this tracker with your current authentication level.

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

Submitted by:  Brock Erwin <berwin>
Submitted on:  Mon 07 Feb 2011 10:36:46 PM UTC  
 
Category: Base/FoundationSeverity: 3 - Normal
Item Group: BugStatus: Invalid
Privacy: PublicAssigned to: None
Open/Closed: Declined

(Jump to the original submission 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>
Project 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>
Project 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>
Project 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>
Project 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>
Project 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>
Project 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>

 

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
  • -unavailable- added by ratmice (Posted a comment)
  • -unavailable- added by nico (Posted a comment)
  • -unavailable- added by CaS (Posted a comment)
  • -unavailable- added by berwin (Submitted the item)
  • -unavailable- added by berwin
  •  

    Do you think this task is very important?
    If so, you can click here to add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.

     

    Please enter the title of George Orwell's famous dystopian book (it's a date):

     

     

    Follow 5 latest changes.

    Date Changed By Updated Field Previous Value => Replaced By
    Tue 08 Feb 2011 05:26:02 PM UTCberwinAttached File-=>Added nsclassfromstring-GNUmakefile.tar.gz, #22626
    Mon 07 Feb 2011 11:06:44 PM UTCCaSStatusNone=>Invalid
      Open/ClosedOpen=>Declined
    Mon 07 Feb 2011 10:36:46 PM UTCberwinAttached File-=>Added nsclassfromstring.tar.gz, #22619
      Carbon-Copy-=>Added -unavailable-

    Back to the top


    Powered by Savane 3.1-cleanup1