Building Unity App to iPad - ios

I'm trying to build my simple app to run on the iPad. What my app is doing is trying to read from the on board pastebin which is having some data sent to it via a second app.
However, upon building the app on xcode I have the following linker errors:
Undefined symbols for architecture armv7: "_importString",
referenced from:
RegisterMonoModules() in RegisterMonoModules.o "_exportString", 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)
Now I know that it is looking at my import and export strings but nothing is ever started with a double underscore. Take a look at my dll file I wrote in XCode:
#define MakeStringCopy( _x_ ) ( _x_ != NULL && [_x_ isKindOfClass:[NSString class]] ) ? strdup( [_x_ UTF8String] ) : NULL
#define GetStringParam( _x_ ) ( _x_ != NULL ) ? [NSString stringWithUTF8String:_x_] : [NSString stringWithUTF8String:""]
//send clipboard to unity
extern "C" const char * importString()
{
NSString *result = [UIPasteboard generalPasteboard].string;
return MakeStringCopy(result);
}
//get clipboard from unity
extern "C" void exportString(const char * eString)
{
[UIPasteboard generalPasteboard].string = GetStringParam(eString);//#"the text to copy";
}
And the sister class I have in my Unity application:
[DllImport("__Internal")]
private static extern string _importString();
//retrieves the clipboard contents from xcode
public static string ImportString()
{
//Debug.Log ("import: "+_importString());
if( Application.platform == RuntimePlatform.IPhonePlayer )
{
return _importString();
}
else
{
return "";
}
}
[DllImport("__Internal")]
private static extern void _exportString(string exportData);
//passes string to xcode and xcode copies to clipboard
public static void ExportString(string exportData)
{
// Debug.Log ("export: "+exportData);
if( Application.platform == RuntimePlatform.IPhonePlayer )
{
_exportString(exportData);
}
}
I have stored the dll file in the following folder structor in Unity:
Assets -> Plugin -> iOS
But I'm at a loss as to how to fix my errors. Can anyone please help?
update
Based on a suggestion below I have ommited the underscore from both the import string and export string and I still have the same issues.

Related

how to solve: symbol(s) not found for architecture in macOS bundle

Im writing simple wrapper for loading leaderboards from game center and it's working like a charm on iOS, but while i build my app on macOS i'm getting this error:
"_gameCenter_loadLeaderboard", referenced from:
_LeaderboardWrapper_gameCenter_loadLeaderboard_m1E818D39D7E09691764495F877AE9D990EC4D432 in F9507B415CD33260EA533B953F7CF7A8.o
(maybe you meant: _LeaderboardWrapper_gameCenter_loadLeaderboard_m1E818D39D7E09691764495F877AE9D990EC4D432)
"_gameCenter_setLoadLeaderboardCallbackHandler", referenced from:
_LeaderboardWrapper_gameCenter_setLoadLeaderboardCallbackHandler_m622CA920AA696EFA52E1BA9706D4A1087FA4F1FF in F9507B415CD33260EA533B953F7CF7A8.o
(maybe you meant: _LeaderboardWrapper_gameCenter_setLoadLeaderboardCallbackHandler_m622CA920AA696EFA52E1BA9706D4A1087FA4F1FF)
ld: symbol(s) not found for architecture x86_64
Undefined symbols for architecture arm64:
"_gameCenter_loadLeaderboard", referenced from:
_LeaderboardWrapper_gameCenter_loadLeaderboard_m1E818D39D7E09691764495F877AE9D990EC4D432 in E59781FE06F50F58456801B2C8EBD151.o
(maybe you meant: _LeaderboardWrapper_gameCenter_loadLeaderboard_m1E818D39D7E09691764495F877AE9D990EC4D432)
"_gameCenter_setLoadLeaderboardCallbackHandler", referenced from:
_LeaderboardWrapper_gameCenter_setLoadLeaderboardCallbackHandler_m622CA920AA696EFA52E1BA9706D4A1087FA4F1FF in E59781FE06F50F58456801B2C8EBD151.o
(maybe you meant: _LeaderboardWrapper_gameCenter_setLoadLeaderboardCallbackHandler_m622CA920AA696EFA52E1BA9706D4A1087FA4F1FF)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
my LeaderboardWrapper.h looks like:
void gameCenter_setLoadLeaderboardCallbackHandler(GameCenter_LoadLeaderboardCallback handler);
void gameCenter_loadLeaderboard(const char* leaderboardId);
enum GameCenterLoadLeaderboardError
{
GCLoadLeaderboard_NoError = 0,
GCLoadLeaderboard_CallbackHandlerNotSet,
GCLoadLeaderboard_ServiceError,
GCLoadLeaderboard_LeaderboardNotFound
};
and LeaderboardWrapper.m:
#import "LeaderboardWrapper.h"
#import <GameKit/GameKit.h>
#import <Foundation/Foundation.h>
#ifdef __cplusplus
extern "C" {
#endif
GameCenter_LoadLeaderboardCallback _gameCenterLoadLeaderboardCallbackHandler = NULL;
void gameCenter_setLoadLeaderboardCallbackHandler(GameCenter_LoadLeaderboardCallback handler)
{
_gameCenterLoadLeaderboardCallbackHandler = handler;
}
void gameCenter_loadLeaderboard(const char* leaderboardId)
{
if(_gameCenterLoadLeaderboardCallbackHandler == NULL)
{
NSMutableDictionary* result = [NSMutableDictionary dictionary];
result[#"LeaderboardId"] = [NSString stringWithUTF8String:leaderboardId];
result[#"Sucess"] = [NSNumber numberWithBool:false];
result[#"Error"] = [NSNumber numberWithInt:GCLoadLeaderboard_CallbackHandlerNotSet];
_gameCenterLoadLeaderboardCallbackHandler([makeResultString(result) UTF8String]);
return;
}
}
#ifdef __cplusplus
}
#endif
Can anyone tell me what im doing wrong?

How to use `-fsanitize-coverage=trace-pc-guard` in swift project?

In a project with language Objective-C, I add -fsanitize-coverage=trace-pc-guard in Other C Flags :
Then I add two methods in project, like belows:
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
static uint64_t N; // Counter for the guards.
if (start == stop || *start) return; // Initialize only once.
printf("INIT: %p %p\n", start, stop);
for (uint32_t *x = start; x < stop; x++)
*x = ++N; // Guards should start from 1.
}
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
if (!*guard) return;
void *PC = __builtin_return_address(0);
char PcDescr[1024];
printf("guard: %p %x PC %s\n", guard, *guard, PcDescr);
}
So I can get information that I wanted.
In swift project I also set Other C Flags.
And add -sanitize-coverage=func、-sanitize=undefined in Other Swift Flags
but I got an error:
Undefined symbol: ___sanitizer_cov_trace_pc_guard_init
How can I solve this problem and get information like oc project.
Just a guess: I don't think "Other Swift Flags" gets passed to the linker invocation -- that would explain the undefined symbols error. Try adding "-fsanitize=undefined" to the Linker Flags.
Another guess: If you were to pass "-fsanitize=undefined" in the Linker Flags for your ObjC project, you probably wouldn't need to provide your own definitions for __sanitizer_cov_*.

Lua module with Visual Studio

I'm trying to make a Lua module with Visual Studio 2013, the main ccp is here along with the module.hpp and the other include is here.
I changed the main ccp to remove a unneeded include file and two unneeded functions so I get this:
#include <lua.hpp>
#include <GeoIP.h>
#include "module.hpp"
static GeoIP * geoip = NULL;
static int load_geoip_database(lua_State * L)
{
const char * filename = luaL_checkstring(L, 1);
if (geoip) GeoIP_delete(geoip);
geoip = GeoIP_open(filename, GEOIP_MEMORY_CACHE);
lua_pushboolean(L, geoip != NULL);
return 1;
}
static int ip_to_country(lua_State * L)
{
if (!geoip) return luaL_error(L, "missing GeoIP database");
const char * ipaddr = luaL_checkstring(L, 1);
const char * country = GeoIP_country_name_by_addr(geoip, ipaddr);
lua_pushstring(L, (country ? country : ""));
return 1;
}
static int ip_to_country_code(lua_State * L)
{
if (!geoip) return luaL_error(L, "missing GeoIP database");
const char * ipaddr = luaL_checkstring(L, 1);
const char * code = GeoIP_country_code_by_addr(geoip, ipaddr);
lua_pushstring(L, (code ? code : ""));
return 1;
}
static int shutdown_geoip(lua_State * L)
{
GeoIP_delete(geoip);
geoip = NULL;
return 0;
}
namespace lua{
namespace module{
void open_geoip(lua_State * L)
{
static luaL_Reg functions[] = {
{ "load_geoip_database", load_geoip_database },
{ "ip_to_country", ip_to_country },
{ "ip_to_country_code", ip_to_country_code },
{ NULL, NULL }
};
luaL_register(L, "geoip", functions);
lua_pop(L, 1);
lua::on_shutdown(L, shutdown_geoip);
}
} //namespace module
} //namespace lua
Visual Studio throws me the following errors:
1>------ Build started: Project: GeoIP, Configuration: Release Win32 ------
1> Main.cpp
1>Main.obj : error LNK2001: unresolved external symbol _GeoIP_delete
1>Main.obj : error LNK2001: unresolved external symbol _luaL_checklstring
1>Main.obj : error LNK2001: unresolved external symbol _luaL_register
1>Main.obj : error LNK2001: unresolved external symbol _lua_pushstring
1>Main.obj : error LNK2001: unresolved external symbol _GeoIP_country_name_by_addr
1>Main.obj : error LNK2001: unresolved external symbol _lua_settop
1>Main.obj : error LNK2001: unresolved external symbol "void __cdecl lua::on_shutdown(struct lua_State *,int (__cdecl*)(struct lua_State *))" (?on_shutdown#lua##YAXPAUlua_State##P6AH0#Z#Z)
1>Main.obj : error LNK2001: unresolved external symbol _GeoIP_country_code_by_addr
1>Main.obj : error LNK2001: unresolved external symbol _GeoIP_open
1>Main.obj : error LNK2001: unresolved external symbol _luaL_error
1>Main.obj : error LNK2001: unresolved external symbol _lua_pushboolean
1>C:\Users\User\Documents\Visual Studio 2013\Projects\Win32Project1\Release\GeoIP_win32.dll : fatal error LNK1120: 11 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
and I dont know what the errors are meaning, the module has been built before by others so the code should be OK.
Looks like you forgot to configure your build so the linker knows what libraries to link to your module. Looks like you should link to GeoIP DLL and, of course, the Lua DLL. In the project's Properties dialog, look for Linker | General | Additional Library Directories, it must indicate the folder where your Lua DLL is located, and the folder where the GeoIP DLL is located. Then look at Linker | Input | Additional Dependencies, it must indicate the name of the Lua export lib for the Lua DLL (such as lua51.lib), and same for GeoIP (something like libgeoip.lib).

OCUnit test cases not running

If I create a new project which includes unit tests, the test cases get called. But when I'm adding tests to an existing project I'm getting the following in the log:
2013-05-21 19:41:08.814 otest[51593:7e03] Unknown Device Type. Using UIUserInterfaceIdiomPhone based on screen size
Test Suite '/Users/impadmin/Library/Developer/Xcode/DerivedData/SmartDiary-frrybdtgyyjgewbialqsmxkwvlxs/Build/Products/Debug-iphonesimulator/testSmartDiary.octest(Tests)'
started at 2013-05-21 14:11:09 +0000
Test Suite 'testShowContacts' started at 2013-05-21 14:11:09 +0000
Test Suite 'testShowContacts' finished at 2013-05-21 14:11:09 +0000.
Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.000) seconds
I've added the SenTestKit to the frameworks, and then added the testing bundle via Add Target.
Where am I going wrong?
Let me add the method and its test case here:
//the method to be tested
-(IBAction)addTask{
if(!([mPriority.text isEqualToString:#"1"] ||[mPriority.text isEqualToString:#"2"] ||[mPriority.text isEqualToString:#"3"] ||[mPriority.text isEqualToString:#"4"] ||[mPriority.text isEqualToString:#"5"]))
{
NSLog(#"Enter valid Priority value");
}
else if ([mTaskName.text isEqualToString:#""]) {
NSLog(#"Task name can't be blank");
}
else{
sqlite3_stmt *statement;
const char *dbPath = [mDatabasePath UTF8String];
//[[appViewController returnObject].mDatabasePath UTF8String];
if (sqlite3_open(dbPath, &mDiary) == SQLITE_OK)
{
NSLog(#"%#",mPriority.text);
NSString *insertSQL2=[NSString stringWithFormat:#"INSERT INTO TODO VALUES(\"%#\",\"%#\",\"%#\",\"%#\",\"%#\")",mStartDate.text,mEndDate.text,mTaskName.text,mTaskDescription.text,mPriority.text];
NSLog(#"%#",insertSQL2);
const char *insert_stmt2 = [insertSQL2 UTF8String];
sqlite3_prepare_v2(mDiary, insert_stmt2,
-1, &statement, NULL);
NSLog(#"%#",mPriority.text);
if (sqlite3_step(statement) == SQLITE_DONE )
{
mStartDate.text=#"";
mEndDate.text=#"";
mTaskName.text=#"";
mTaskDescription.text=#"";
mPriority.text=#"";
}
else {
NSLog(#"failed to add");
}
sqlite3_finalize(statement);
sqlite3_close(mDiary);
}
}
}
//here's the test:
-(void)testAddTask
{
AddTaskViewController *obj;
obj = [[AddTaskViewController alloc]init];
obj.mTaskName.text = #"t1";
obj.mTaskDescription.text = #"t2";
obj.mStartDate.text = #"56987";
obj.mEndDate.text = #"55425";
obj.mPriority.text = #"3";
[obj addTask];
sqlite3_stmt *statement;
const char *dbpath = [obj.mDatabasePath UTF8String];
if (sqlite3_open(dbpath,&mDiaryTest)== SQLITE_OK) {
NSString *selectSQL = [NSString stringWithFormat:#"SELECT * FROM TODO WHERE mTaskName = \"%#\"",obj.mTaskName.text];
const char *query_stmt = [selectSQL UTF8String];
if (sqlite3_prepare_v2(mDiaryTest,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_ROW)
{
testString = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
}
}
}
sqlite3_finalize(statement);
sqlite3_close(mDiaryTest);
NSLog(#"%#",testString);
STAssertEquals(testString,#"t2",#"should be equal");
}
I found that in target dependencies the project was unchecked. I checked it and tested again, whereupon I'm getting the following errors:
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_AddTaskViewController", referenced from:
objc-class-ref in testAddTask.o
"_sqlite3_close", referenced from:
-[testAddTask testAddTask] in testAddTask.o
"_sqlite3_column_text", referenced from:
-[testAddTask testAddTask] in testAddTask.o
"_sqlite3_finalize", referenced from:
-[testAddTask testAddTask] in testAddTask.o
"_sqlite3_open", referenced from:
-[testAddTask testAddTask] in testAddTask.o
"_sqlite3_prepare_v2", referenced from:
-[testAddTask testAddTask] in testAddTask.o
"_sqlite3_step", referenced from:
-[testAddTask testAddTask] in testAddTask.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I know this is probably going off topic, since the original question was entirely different, but can anyone please tell me why these errors are coming? I've added the necessary frameworks.
As you are testing UIKit dependent stuff, you want to run Application Tests. Make sure you have set the Bundle Loader and Test Host build settings (refer to the documentation).
Further you have to link the libsqlite3.0.dylib against your tests target too, because you are using sqlite functions in your unit tests.

What is the simplest way to retrieve the device serial number of an iOS device using MonoTouch?

Does MonoTouch have a simple mechanism for retrieving the device serial number (not UDID) of an iOS device? Is there a third-party library which I can use to obtain this?
In case it matters, I'm looking to use this functionality in an in-house application and am not concerned with the App Store approval process.
UPDATE: from iOS 8, we cannot retrieve the serial number of our iDevice.
To retrieve iphone serial number from Monotouch, you can use this technic:
Create a static library .a from XCode that have a function to get serial number
In MonoDevelop, create a binding project to bind you .a library into C# classes/functions (http://docs.xamarin.com/guides/ios/advanced_topics/binding_objective-c_libraries)
In your application, you call this binding library (in step 2).
For detail:
STEP 1. In my library.a, I have a class DeviceInfo, here is the implementation to get Serial number
#import "DeviceInfo.h"
#import <dlfcn.h>
#import <mach/port.h>
#import <mach/kern_return.h>
#implementation DeviceInfo
- (NSString *) serialNumber
{
NSString *serialNumber = nil;
void *IOKit = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW);
if (IOKit)
{
mach_port_t *kIOMasterPortDefault = dlsym(IOKit, "kIOMasterPortDefault");
CFMutableDictionaryRef (*IOServiceMatching)(const char *name) = dlsym(IOKit, "IOServiceMatching");
mach_port_t (*IOServiceGetMatchingService)(mach_port_t masterPort, CFDictionaryRef matching) = dlsym(IOKit, "IOServiceGetMatchingService");
CFTypeRef (*IORegistryEntryCreateCFProperty)(mach_port_t entry, CFStringRef key, CFAllocatorRef allocator, uint32_t options) = dlsym(IOKit, "IORegistryEntryCreateCFProperty");
kern_return_t (*IOObjectRelease)(mach_port_t object) = dlsym(IOKit, "IOObjectRelease");
if (kIOMasterPortDefault && IOServiceGetMatchingService && IORegistryEntryCreateCFProperty && IOObjectRelease)
{
mach_port_t platformExpertDevice = IOServiceGetMatchingService(*kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
if (platformExpertDevice)
{
CFTypeRef platformSerialNumber = IORegistryEntryCreateCFProperty(platformExpertDevice, CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0);
if (CFGetTypeID(platformSerialNumber) == CFStringGetTypeID())
{
serialNumber = [NSString stringWithString:(__bridge NSString*)platformSerialNumber];
CFRelease(platformSerialNumber);
}
IOObjectRelease(platformExpertDevice);
}
}
dlclose(IOKit);
}
return serialNumber;
}
#end
STEP 2. In ApiDefinition.cs of my Binding Library project in Monotouch, I add this binding:
[BaseType (typeof (NSObject))]
public interface DeviceInfo {
[Export ("serialNumber")]
NSString GetSerialNumber ();
}
STEP 3. In my application, I import Reference to Binding library project in step 2, then add
using MyBindingProject;
...
string serialNumber = "";
try {
DeviceInfo nativeDeviceInfo = new DeviceInfo ();
NSString temp = nativeDeviceInfo.GetSerialNumber();
serialNumber = temp.ToString();
} catch (Exception ex) {
Console.WriteLine("Cannot get serial number {0} - {1}",ex.Message, ex.StackTrace);
}
Hope that helps. Don't hesitate if you have any question.

Resources