7

C# code : (windows)

Assembly assembly = Assembly.LoadFrom(AssemblyPath);
System.Type[] objTypes = assembly.GetTypes();
Type libType = null;

I want to achieve same for Mac where AssemblyPath is path of static library (libTEST.a) or dylib file. Is it possible in Objective-C (Mac)? I tried with NSBundle. But i want some good solution.

Devolus
  • 21,661
  • 13
  • 66
  • 113
user3200854
  • 147
  • 2
  • 8
  • What did you try with NSBundle, and why is it a "bad solution"? And what about dlopen(), which was already suggested in an answer http://stackoverflow.com/a/21338282/1187415 to your previous similar question? – Martin R Jan 27 '14 at 07:56
  • 3
    Btw, instead of repeating your question http://stackoverflow.com/questions/21325604/how-to-load-dll-file-which-returns-assembly-in-objective-c and ignoring a given answer, you could try to improve the question or leave a comment if the answer does not solve your problem. – Martin R Jan 27 '14 at 08:15
  • Hi... I think .a (static library) file is not supported in NSBundle. I used this... Class exampleClass; id newInstance; NSString *str = @"/Users/Desktop/libCDT.ChunkUtil.a"; NSBundle *bundleToLoad = [NSBundle bundleWithPath:str]; if (exampleClass == [bundleToLoad classNamed:@"IReaderClass"]) { newInstance = [[exampleClass alloc] init]; // [newInstance doSomething]; } But bundleToLoad object contains Null value... So what to do? – user3200854 Jan 27 '14 at 10:58

2 Answers2

17

First off, this has precisely nothing to do with Xcode.

Now, you can't load static libraries dynamically, because a static library is just a collection of object files, which are not, by themselves, executable.

In order to load a dynamic library, use the dlopen() API:

void *handle = dlopen("/path/to/library.dylib", RTLD_LAZY);

To get a C function pointer:

int (*computeAnswer)(void) = dlsym(handle, "ComputeAnswer");
int answer = computeAnswer(); // 42

To get a C++ function pointer without extern "C" linkage (mangled name):

int (*mangledFunction)(void) = dlsym(handle, "i$mangledFunction_@v");

You can even hack yourself through the Objective-C naming convention of the linker compiler:

@class MyShinyClass;
Class cls = dlsym(handle, "OBJC_CLASS_$_MyShinyClass");

MyShinyClass *instance = [[cls alloc] init];

When you're done with the library, dispose of it:

dlclose(handle);
  • @user3200854 It can't. You can't dynamically load a static library. –  Jan 28 '14 at 06:52
  • H2CO3 : Thanks for your help.. I created framework and loaded using dlopen function. Now i have framework_handle. Is it possible to get class name from framework_handle object? – user3200854 Jan 29 '14 at 03:38
  • Hi... I had done this by using NSBundle.. I am loading framework dynamically. like this... NSBundle *b = [NSBundle bundleWithPath:AssemblyPath]; if ( [b load] ){..} Now i want all classes list from this loaded framework. And i want to check the basetype of it i.e. base class name. If the base class name is same as required class name then i want to create an instance of that paricular class... How it possible? – user3200854 Jan 29 '14 at 11:01
  • @user3200854 You can get a list of classes using `objc_getClassClist()` and you can get the string corresponding to the principal class of the bundle by looking at its info dictionary. There's an `NSPrincipalClass` key that does exactly what you want. –  Jan 29 '14 at 12:07
  • hi... but i have loaded my framework dynamically.. i want all classes from that loaded framework only.. objc_getClassClist() retuns no of classes... I don't want that... I just want classes which are loaded dynamically by framework. Can you please give me any suggestion or feedback? Please.. – user3200854 Jan 30 '14 at 04:07
  • @user3200854 what do you mean by "returns no of classes"? it returns all classes. You can filter those on class name using `- [NSBundle classNamed]`. But how'bout you do some research yourself? It's getting tiring. –  Jan 30 '14 at 06:30
  • Sorry to disturbing again and again... but as per my understanding objc_getClassClist returns all class which are in the system.. But actually i want to achieve something like this :- i have loaded my framework using dlopen() which returns handle.. my framework contains two classes.. so using dlopen heandle pointer i want that classes only which are in the framework... so how it possible?? Please help me... and thank you for your valuable time... – user3200854 Jan 31 '14 at 06:56
  • @user3200854 read my previous comment. Really. **I mean, read it carefully.** "You can filter those on class name using `- [NSBundle classNamed]`". If you can't implement a simple "filter-on-property" algorithm with a linear search and a unary predicate, then google it. It's really just a glorified for loop. You look at the i-th class, you check if its name is inside the bundle, you append it to a list/array/set if it is. –  Jan 31 '14 at 10:12
0

I would add to what was said earlier, that you need to bridge the class from the dlsym, which returns a C type void*.

So in that case, it will mean doing something of a sort:

@class MyShinyClass;
Class cls = (__bridge Class)dlsym(handle, "OBJC_CLASS_$_MyShinyClass");

MyShinyClass *instance = [[cls alloc] init];

Notice the (__bridge Class) addition there.

For further reference: Pass an Objective-C object to a function as a void * pointer

YanivH
  • 539
  • 4
  • 18