unrecognized selector when using category in static library.
I searched in google and found this?
http://www.dribin.org/dave/blog/archives/2006/03/13/static_objc_lib/
but I am still confused:
1、If I have object.h/.m and object+category.h/.m, and #import "object+category.h" in object.m, I add these to my project as source code, it works fine(no unrecognized selector error). But if I complie these to a static library and add to my project, crash with unrecognized selector.
So what's the different between these two ways? Why first way can find the selector and second way cannot?
2、The article says "As an optimization, the linker only chooses the object files that are required to resolve symbols." Same with static library and source code? Means If I have object.h/.m and object+category.h/.m as source code in my project and object+category.h/.m is never used. Will all those compiled .o files link to final .app?
3、How does the xcode linker know object+category.o is required and link it to .app if symbol is just created for each class, not each method? And when the link happen for object+category.o, compile time or runtime?
Related
I needed a sketch/painting control for my Xamarin.iOS project, and while I couldn't seem to find one compatible with C# I did find a good component available written in Objective C. https://github.com/acerbetti/ACEDrawingView
I've done Xamarin bindings before, so I had hoped that the process would be fairly simple, but unfortunately I've hit a few roadblocks along the way.
I started off creating my static library and used an ant build script to make a FAT binary to cover devices and the simulator:
snippet of my ant script
AceDrawingViewSDK.a: libAceDrawingView-i386.a libAceDrawingView-armv7.a libAceDrawingView-armv7s.a libAceDrawingView-arm64.a xcrun -sdk iphoneos lipo -create -output $# $^
Next, I ran
sharpie bind --sdk=iphoneos10.1 *.h
on the header files to get my ApiDefinitions and Structs and Enum files.
I checked and removed a the Verify attributes. (They all looked fine.) But this is where some of my other issues started.
The type ACEDrawingLabelViewTransform' already contains a definition forTransform' (CS0102) (AceDrawingViewBinding).
For the sake of just trying to move on and get something working, I just commented out this reference.
I then got multiple problems similar to this:
The type or namespace name `IACEDrawingTool' could not be found. Are you missing an assembly reference? (CS0246) (AceDrawingViewBinding)
I figured it related to this:
// #interface ACEDrawingPenTool : UIBezierPath
[BaseType(typeof(UIBezierPath))]
interface ACEDrawingPenTool : IACEDrawingTool
and this:
// #protocol ACEDrawingTool
[Protocol, Model]
[BaseType(typeof(NSObject))]
interface ACEDrawingTool
I tried to fix this my making the interface name consistent (I tried both IACEDrawingTool and ACEDrawingTool.) Doing this got past this error and allowed me to compile
One of my enums came out as
[Native]
public enum ACEDrawingMode : nuint
{
Scale,
OriginalSize
}
I couldn't find how to handle [Native] in this case (so once again, for testing sake I removed it.) I tried using removing the nuint from the enum and using uint. Either approach seemed to fix the error.
So with those errors fixed I was able to generate the .dll from my binding project and add it to my main project.
Now, I am getting 2 more issues.
If I build and deploy to the simulator I am able to run my app up until the point that I try to create a new instance of the ACEDrawingView from the binding. I get:
Could not create an native instance of the type 'ACEDrawingView': the native class hasn't been loaded.
It is possible to ignore this condition by setting ObjCRuntime.Class.ThrowOnInitFailure to false.
If I try to build and deploy to my phone I get different errors in the build phase which prevents it from launching on the device at all:
MTOUCH: error MT5211: Native linking failed, undefined Objective-C class: ACEDrawingArrowTool. The symbol 'OBJC_CLASS$ACEDrawingArrowTool' could not be found in any of the libraries or frameworks linked with your application.
MTOUCH: error MT5211: Native linking failed, undefined Objective-C class: ACEDrawingDraggableTextTool. The symbol '_OBJC_CLASS$ACEDrawingDraggableTextTool' could not be found in any of the libraries or frameworks linked with your application.
MTOUCH: error MT5211: Native linking failed, undefined Objective-C class: ACEDrawingEllipseTool. The symbol '_OBJC_CLASS$_ACEDrawingEllipseTool' could not be found in any of the libraries or frameworks linked with your application.
...and so on.
I've tried going back, rereading and redoing steps and have tried to reuse some of the scripts and settings from my previous successful bindings with no luck.
Does anyone have suggestions for what might fix these issues?
The type or namespace name `IACEDrawingTool' could not be found.
Add a new interface, like this interface IACEDrawingTool{ }
public enum ACEDrawingMode : nuint
Change the nuint to ulong
I have two C projects that pull in the same library.
One project compiles and links fine, the other gets an "unresolved external reference" linker error for a symbol referenced inside a function which both projects call from the same static library.
As far as I can tell, all the linker and code generation properities of importance are equal between the two.
Is there a way to use the working project, to figure out where the linker in THAT project finds the symbol? I've been using trial and error, including more and more of the libraries from one project into the other with no success.
I found what I wanted! In the Project Properties, under Linker->Debugging, there is an option named "Generate Map File". This can be done on the command-line with /MAP.
The generated map file gets the same name as the project (by default) with .map as file extension. It is a text file containing, among other things, the library name where each symbol is defined.
Using the map file for my project that builds, I was able to quickly find the definition of the symbol missing from my broken project.
Is there any way to get the address of the function which is defined in static library (.lib) which is been linked to some application .
Thanks
A static library is nothing but an archive (like a .ZIP file) of object files.
When you link against a static library the linker will check which of these object files are needed and link them to the executable. The result is exactly the same as if you directly compiled the source code of the library in your project.
So the actual question is: Is it possible to find out the address of a non-static function in an executable file?
Some linkers (like GNU) generate a symbol table by default even in a project without debugging information. You could parse the symbol table in this case. However many linkers do not create this symbol table. In this case the information of all function names is lost so you do not have any chance to get information about the address without debugging information.
How to build a .bundle from source code?
This might sound like a simple problem but it has been hurdling me for a week...
Here is my problem:
I have a bunch of .c and .h files that are organized in a folder and its sub folders. The source code was written and compiled with gcc make and tested by many other make tools. The source code has some utilities and command line tools and it has more code that serve as library for those utilities and tools. It is the files that serve as libraries that I want to reuse. (By library I don't mean static library or something, I just mean that some .c and .h files in certain subfolders provide functions that can be called by some other .c files. I want to be able to call those functions, too)
Yet my problem is more complex than that: I need to build those .c and .h into a bundle to reuse it. I am not writing my application in C; I am developing in Unity and Unity can only take in .bundle files on Mac OS.
Here is my goal:
Organize the source code folder in a proper way so that I can build them into a bundle in Xcode 4.
Here is where I got stuck:
When building the project I got the following error:
Duplicate symbol _main in
/Users/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpofnfxalwimtyniq/Build/Intermediates/ccn.build/Debug/ccn.build/Objects-normal/i386/ccndsmoketest.o
and
/Users/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpofnfxalwimtyniq/Build/Intermediates/ccn.build/Debug/ccn.build/Objects-normal/i386/ccnd_main.o
for architecture i386
I can relate to this error because I can find lots of main entries in the source code. Most of them are test utilities.
Here is what I tried:
I tried removing all those utility .c files but with no luck. The error is still there. I delete and delete until some files cannot find the definition of the function they are calling. So I had to stop there.
Though I wasn't able to build a bundle I was able to build a C/C++ static library (with an .a extension). After I got the .a file I tried to put it into another Xcode project and tried to build it into a bundle. I could build a bundle in that way, but then I had problem accessing the content of the bundle. How do I call functions defined in a .a static library if that library is hidden in a bundle? I read about Apple's documentation which says:
Note: Some Xcode targets (such as shell tools and static libraries) do
not result in the creation of a bundle or package. This is normal and
there is no need to create bundles specifically for these target
types. The resulting binaries generated for those targets are intended
to be used as is.
(quoted from: https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFBundles/AboutBundles/AboutBundles.html#//apple_ref/doc/uid/10000123i-CH100-SW1)
Here is what I thought about:
I thought about replacing all main with something like main_sth. But the source code was not written by me so I didn't want to modify it. (It just doesn't feel like a proper way of doing things to me...)
I learnt that Xcode has gcc compiler built in. So I guess if gcc can make it, so can Xcode? It's just a wild guess - I am not familiar with Xcode and gcc.
Here is a summary of my questions:
Is there a way to properly organize a pile of code previously compiled and made by gcc make so that they can be built into an Xcode bundle?
Is it meaningful to put a .a library in an Xcode project and build it into a bundle? If it is meaningful, how do I call functions defined in .a after it is built into a bundle?
Is it proper to just replace all main() entries with something else?
Alright I think I have figured out at least one solution to the problem.
The duplicate main error was caused by a bunch of main entries in my source code. When the code was compiled by gcc make, I guess the author defined a sort of compilation order so that duplicate mains won't be an issue. (If you know how to do this, please let me know. I barely know make tools.) But when I just add the entire source code folder into my Xcode project, of course Xcode would complain during linking...
As I was unwilling to modify the source code (because the source code library is not developed by me), I decided to use another strategy to walk around this problem.
If your duplicate main error was reported from your own code, you can stop reading here. But if you are like me, with a bunch of gcc compiled source code and badly need a bundle yet don't know what to do, I may be able to help.
Okay here is what I did:
I set up an empty workspace.
I built a C/C++ static library project.
Import my entire source code folder into the static library project.
Set some header search path for the static library project.
Build the static library project. (Now I have a .a library which I could link against)
I set up another project, with a bundle target.
At the bundle project -> Build Phases -> Link Binary with Libraries, add the .a library that I just built.
At the bundle project -> edit scheme -> Build, add the static library project to the scheme and move it up the list so that it is built prior to my bundle project.
Then add .h files of my library project to my bundle project as references.
After that, add a .c file in my bundle project that basically functions as a wrapper. I picked a function that I want to call in Unity, wrote a wrapper function in the new .c file, and was able to build the bundle.
After several trial and error, I was able to import the bundle into Unity and was able to call the test function from Unity.
I was really excited about this! Though it's not completed yet I think this gives me hope and I am confident I can use the source code now! And the best thing about this solution is that I don't have to modify the library code developed by others. Whenever they update their code, I just update my .a library and that's it!
Though I have listed 11 steps I still feel that there are lots of details that I missed. So here are my references:
I followed this tutorial to build my source code into a static library: http://www.ccnx.org/?post_type=incsub_wiki&p=1315
I followed this blog to link static library against my bundle code and twist build phases and search headers: http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/
I followed this doc to import my bundle to Unity3D Pro as a plugin: http://unity3d.com/support/documentation/Manual/Plugins.html
I strongly recommend the second reference because that's what solved my problem!
Though the problem is almost solved there are still a few things that I haven't figured out:
I don't know if a wrapper function is at all necessary. I will try this out tomorrow and come back to update.
-- I am coming back to update: the wrapper function is NOT necessary. Just make sure you have all the headers in your bundle project and you will be able to use all the data structures and call functions defined in your headers.
I haven't used NSBundle class though I read a few docs about it. Previously I was thinking about using that class to access my .a library encapsulated in my bundle, but as I found the solution I wrote above, I didn't try the class out.
Lastly, if you have better solution, please don't hesitate to let me know!
I tried to follow the steps in the accepted answer, but had no luck. In the end, I realised step 10 needed to be modified slightly:
Create a dummy.c under (.bundle) project and the dummy.c can just be totally empty.
Remove the setting for the library you want to link inside Link Binary With Libraries
Instead use -Wl,-force_load,$(CONFIGURATION_BUILD_DIR)/libYourLib.a or -all_load to Other Linker Flags
PS: And also can use sub-project instead of workspace. and use Target Dependencies instead of Edit Scheme to achieve the same effect.
I am building a Visual C++ 6.0 workspace in Visual Studio 2010, so that it'll update some dependencies
I have all the files and dll's it is looking for, it builds but then fails at linking with this error
1>LINK : fatal error LNK1181: cannot open input file '\Projects\exe\CRelease/api.lib'
I have api.dll which it needs to build, but I don't have a .lib file version of it. and even if I did (like if I somehow converted the .dll into a .lib), I wouldn't know where to place it in a directory structure
how do I "fix" this?
guidance appreciated, thank you
Normally api.dll would have an accompanying import library called api.lib which is what you need to link to. The import library is different to a statically-compiled version of api (which would also likely be called api.lib) - it's more like a list of available functions provided by the dll, and so will usually be much smaller than a corresponding static library.
If you do find or get api.lib, it doesn't really matter where it lives, as long as it can be accessed by your linker.
If you don't find the import library, you're looking at doing explicit run-time linking where api.dll is loaded and unloaded explicitly in your code, and api's exported functions are called through function pointers.