I'm trying to use an iOS native framework inside Unity, but I don't know how.
Inside my C# script, I call a native function like this :
[DllImport ("__Internal")]
private static extern void writeHello();
void Start () {
writeHello();
}
I have drag the iOS framework inside my project like this :
Link to my image
But when I deploy my app on iPad, xCode showing this error :
Undefined symbols for architecture armv7: "_writeHello", referenced
from:
RegisterMonoModules() in RegisterMonoModules.o ld: symbol(s) not found for architecture armv7 clang: error: linker command failed with
exit code 1 (use -v to see invocation)
I don't understand why, and I don't know if what I'm trying to do is possible.
Help! :)
Thanks,
Sennin
The iOS framework must be put in the xCode generated project, not in unity.
And the framework's functions must be wrapped in an extern "C" block (as shown here).
Then you will be able to use it in C# with dllimport.
The doc says that all files with extensions .a,.m,.mm,.c,.cpp located in the Assets/Plugins/iOS folder will be merged into the generated Xcode project automatically. The docs also says that subfolders are currently not supported, so, in your example, the "framework-helloUnity.framework" folder will be ignored.
It is important to note that .m files default to C-style bindings, while .mm files default to C++-style bindings. In other word, unless you use the extern "C" keyword, as Heilo suggested, your functions won't be found if you put them in .mm or .cpp files.
In other words, if you put the following:
void writeHello() {}
in a file named Assets/Plugins/iOS/myTestFile.m, your code should compile.
Found the solution thanks to this post : Calling Objective-C method from C++ method?
By doing like that :
void myWriteHello( void *test) {
[(id)test writeHello];
}
- (void) writeHello
{
NSLog(#"Hello World!");
}
and calling my C function from Unity
You have write the following function in your Xcode project any class
extern "C"
{
-(void) writeHello
{
}
}
Related
Define a method in the .mm file
#if defined(__cplusplus)
extern "C"{
#endif
extern void UnitySendMessage(const char* obj, const char* method, const char* msg) __attribute__ ((weak));;
extern NSString* _CreateNSString (const char* string);
#if defined(__cplusplus)
}
#endif
#interface UnityAdapter ()
...
Called in #implementation UnityAdapter()
UnitySendMessage("PottingMobile", "bannerDidLoadAd", "");
I need help solving the following error:
ld: warning: Could not find auto-linked framework 'FBSDKCoreKit'
Undefined symbols for architecture armv7:
"_UnitySendMessage", referenced from:
-[UnityAdapter bannerDidLoadAd] in UnityAdapter.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
when i don't use UnitySendMessage method, everthing is ok.
I want to write a framework for bridging unit and iOS projects. When I use it in a unit packaged project, no problem. When I put the bridging file into my own framework, I will report an error. There is nothing in the framework project. Do I need to integrate unit's lib? If so, how to integrate? Can you give me a website? Thank you.
Unity is currently doing this with their library feature.
You can look at their solution.
If you need a solution now: Have a look at https://github.com/jiulongw/swift-unity. It's all automated and a good starting point, but missing the library feature.
This project shows how to make an actual library: https://github.com/forestlin1212/unity-ios-framework (But for an older Unity version and not automated)
We have some functions made available to us in iOS static library. There is a header (.h) and the compiled (.a) file. Is there any way that the functions in the static library can be called from a command line ( either OS X, Windows or Linux )? I have researched this for couple of days now and I am starting to doubt if this is even possible? We don't deal with Apple/iOS/xcode environment and the vendor only has this static library. Any hints? If it is possible in anyway I am open to reading any and very documentation but at this time I am in doubt if this is even possible? thanks
While checking out what is possible, I ran this
lipo -info libExaNumberCalc.a
I ran the above and it says
Architectures in the fat file: libExaNumberCalc.a are : i386 armv7 x86_64 arm64
Wonder if the above adds any hope?
The first thing that springs to mind is that you could write thin wrapper around your library function and build/run it. Something like
// main.c
#include "your_library_header.h"
int main(int argc, char *argv[])
{
// parse & pass parameters if necessary from command line
your_lib_function();
return 0;
}
Build with something like
clang main.c -o output.file -lyourlibrary
I tried calling UnitySendMessage method in my iOS Framework project using swift language but it is showing this error-
Use of unresolved identifier 'UnitySendMessage'
Here is the code snippet for my swift file-
import Foundation
#objc public class Example : NSObject{
#objc open static let shared = Example()
#objc open func printMsg(){
print("\(#function) is called with message:");
UnitySendMessage("CallbackTarget", "OnCallFromSwift", "Hello, Unity!");
}
}
Getting stuck here, can you please tell me what am I missing?
check Answer here.
UnitySendMessage is in libiPhone-lib.a, and as far as I can tell, the
Unity folks don't include any header that declares it.
I just added the following to my code
extern void UnitySendMessage(const char *, const char *, const char
*);
If you look at the generated AppController.mm, they basically do the
same thing for the various UnitySendXXX functions, rather than
including a header.
Having said that, while you will be able to build a library that calls
UnitySendMessage, that library probably won't work unless it's linked
into a Unity project, since UnitySendMessage is going to require more
than just libiPhone-lib.a to actually work.
Just add this code to your Bridging-Header.h file:
#import "UnityInterface.h"
Make sure that your files are in the XCode project that was build from Unity, so the actual UnityInterface file that is created by unity is present.
Worked for me :)
I'm getting crazy about this issue!
One of errors I get is the next one:
Undefined symbols for architecture i386:
"_zipOpen", referenced from:
-[ZipArchive CreateZipFile2:] in ZipArchive.o
The peace of code when I call that method (I use objective-c++ there just in the case it matters):
#implementation ZipArchive
...
-(BOOL) CreateZipFile2:(NSString*) zipFile
{
_zipFile = zipOpen( (const char*)[zipFile UTF8String], 0 );
}
in the .h file I have
zipFile _zipFile;
and in other place:
typedef voidp zipFile;
where
typedef void *voidp;
Ok, I know it shouldn't be working probably. But it worked great before. The things changed with the new target I added for unit test.
I'll greatly thankful for any your help!
Okay, from the error
Undefined symbols for architecture i386:
"_zipOpen", referenced from:
-[ZipArchive CreateZipFile2:] in ZipArchive.o
we can tell that the prototype for zipOpen() function is declared as a C function (extern "C"), as its name isn't mangled.
So, there are basically 2 options why this error is coming up:
The zipOpen() implementation isn't being linked against your program at all (forgot to add the file/library to your build, #ifdef'd out, etc.)
The zipOpen() implementation is getting C++, not C linkage, for some reason. Maybe you've accidentally placed it inside a namespace, or the .cpp file doesn't include the header with the extern "C" declaration of the function.
We can't say which it is based on the information provided.
check wether function declaration inside a header file equals to function prototype in an implementation file
I am new to Objective-C and a bit rusty at using C++ and templates, and I am not sure why I am having this link error.
I have a header file that contains definitions similar to these:
struct Info {
std::string name;
};
typedef std::map<std::string, Info> InfoMap;
void Validate(InfoMap* infoMap);
#interface InfoValidator : NSObject
{
}
+(InfoValidator*) getInstance;
-(void) validate:(InfoMap*)infoMap;
#end
I also have an .mm file that contains the following definition for the (global) Validate() method:
void Validate(InfoMap* infoMap)
{
[[InfoValidator getInstance] validate:infoMap];
}
When I call Validate() from a C++ class (defined in an .mm file), I receive the following error:
Undefined symbols for architecture armv7:
Validate(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Info, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, > std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, ?> std::allocator<char> > const, Info> > >*)",
referenced from:
ItemInterface::ValidateItems(int, char const**)in iteminterface.o
ld: symbol(s) not found for architecture armv7
collect2: ld returned 1 exit status
The file has been added to the project, and it is the only link error I get. Thanks for any help.
Did you rename Market_Validate to Validate for the code you've quoted here? The link error refers to the former, which doesn't exist in the code given.
If so, the code looks correct in isolation, I suspect there's something outside the code you've shown going wrong. Make sure both .mm files are in fact being compiled and linked. Check that both include the same header file with your Validate() function declaration. Since you have renamed the function before posting it here, make sure you're using the same name for it throughout your code (specifically, the declaration and definition must match exactly).
Are you using namespaces anywhere? Make sure you didn't accidentally put your function definition inside a namespace if the declaration isn't - they'll be referring to different functions.
Note that the code as you've posted it won't compile, as there's a semicolon missing after your struct Info definition. It's often impossible to help once the code has been altered for the question without testing that the problem still exists with that code. If you're still stuck, I suggest trying to amend the code in this question so it will compile and show the same link error. If you can't reproduce it, take a good look at the differences between your 'real' code and the question code.