I am attempting to create a C# binding to NSLog for use in my MonoTouch app.
Here is the link to the iOS documentation on NSLog (NSLog). So far I haven't had much luck in figuring out the exact syntax. Below is my current code:
using System;
using System.Runtime.InteropServices;
namespace CustomTableDemo
{
public static class FoundationFunctions
{
[DllImport("/System/Library/Frameworks/Foundation.framework/Foundation")]
public extern static void NSLog(string format, params string[] messages);
}
}
Then I call the function as follows:
Console.WriteLine("Before NSLog attempt...");
FoundationFunctions.NSLog("%@", "Hello World");开发者_Python百科
Then the app crashes and this is my log file.
Before NSLog attempt...
Stacktrace:
at (wrapper managed-to-native) CustomTableDemo.FoundationFunctions.NSLog (string,string[]) <IL 0x000b1, 0xffffffff>
at CustomTableDemo.AppDelegate.FinishedLaunching (MonoTouch.UIKit.UIApplication,MonoTouch.Foundation.NSDictionary) [0x0000a] in /Users/bartsipes/Projects/CustomTableDemo/CustomTableDemo/Main.cs:31
at (wrapper runtime-invoke) <Module>.runtime_invoke_bool__this___object_object (object,intptr,intptr,intptr) <IL 0x00066, 0xffffffff>
at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <IL 0x0009f, 0xffffffff>
at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x00038] in /Developer/MonoTouch/Source/monotouch/monotouch/UIKit/UIApplication.cs:26
at MonoTouch.UIKit.UIApplication.Main (string[]) [0x00000] in /Developer/MonoTouch/Source/monotouch/monotouch/UIKit/UIApplication.cs:31
at CustomTableDemo.Application.Main (string[]) [0x00000] in /Users/bartsipes/Projects/CustomTableDemo/CustomTableDemo/Main.cs:14
at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff>
Native stacktrace:
0 CustomTableDemo 0x000c55a3 mono_handle_native_sigsegv + 343
1 CustomTableDemo 0x0000f7e8 mono_sigsegv_signal_handler + 322
2 libSystem.B.dylib 0x999fb05b _sigtramp + 43
3 ??? 0xffffffff 0x0 + 4294967295
4 CoreFoundation 0x012fc317 __CFStringAppendFormatCore + 103
5 CoreFoundation 0x01245507 _CFStringCreateWithFormatAndArgumentsAux + 119
6 CoreFoundation 0x012cd1ee _CFLogvEx + 142
7 Foundation 0x0065a9a4 NSLogv + 143
8 Foundation 0x0065a913 NSLog + 27
9 ??? 0x07fdd694 0x0 + 134076052
10 ??? 0x05e26c1a 0x0 + 98724890
11 ??? 0x05e26eeb 0x0 + 98725611
12 CustomTableDemo 0x0000f5a3 mono_jit_runtime_invoke + 1332
13 CustomTableDemo 0x001d9411 mono_runtime_invoke + 137
14 CustomTableDemo 0x0027d9d7 monotouch_trampoline + 2527
15 UIKit 0x00884c89 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
16 UIKit 0x00886d88 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 439
17 UIKit 0x00891617 -[UIApplication handleEvent:withNewEvent:] + 1533
18 UIKit 0x00889abf -[UIApplication sendEvent:] + 71
19 UIKit 0x0088ef2e _UIApplicationHandleEvent + 7576
20 GraphicsServices 0x01a94992 PurpleEventCallback + 1550
21 CoreFoundation 0x012f5944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
22 CoreFoundation 0x01255cf7 __CFRunLoopDoSource1 + 215
23 CoreFoundation 0x01252f83 __CFRunLoopRun + 979
24 CoreFoundation 0x01252840 CFRunLoopRunSpecific + 208
25 CoreFoundation 0x01252761 CFRunLoopRunInMode + 97
26 UIKit 0x008867d2 -[UIApplication _run] + 623
27 UIKit 0x00892c93 UIApplicationMain + 1160
28 ??? 0x05e222db 0x0 + 98706139
29 ??? 0x05e220ac 0x0 + 98705580
30 ??? 0x05e21e7c 0x0 + 98705020
31 ??? 0x05e21cd4 0x0 + 98704596
32 ??? 0x05e21e26 0x0 + 98704934
33 CustomTableDemo 0x0000f5a3 mono_jit_runtime_invoke + 1332
34 CustomTableDemo 0x001d9411 mono_runtime_invoke + 137
35 CustomTableDemo 0x001dba70 mono_runtime_exec_main + 669
36 CustomTableDemo 0x001dae7e mono_runtime_run_main + 843
37 CustomTableDemo 0x0009c573 mono_jit_exec + 200
38 CustomTableDemo 0x00002df0 main + 4060
39 CustomTableDemo 0x00001bf9 _start + 208
40 CustomTableDemo 0x00001b28 start + 40
Debug info from gdb:
dyld: could not load inserted library: /Users/bartsipes/Library/Application Support/iPhone Simulator/4.3/Applications/599C50F9-29E2-4402-AA84-7B6DC1A1CD36/CustomTableDemo.app/monotouch-fixes.dylib
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================
The reason it does not work is because P/Invoke turns params arguments into an array, which is not what NSLog expects. NSLog expects a variable list argument on the stack as opposed to a single argument on the stack that points to an array.
The simple solution is to provide multiple overloads, like this:
[DllImport (...)]
public extern static void NSLog(string format, string arg1);
[DllImport (...)]
public extern static void NSLog(string format, string arg1, string arg2);
[DllImport (...)]
public extern static void NSLog(string format, string arg1, string arg2, string arg3);
If you do not depend on the NSLog string formatting rules, you only need the first version, and then you can wrap it a method that does:
public void MyLog (string format, params object [] args)
{
NSLog (String.Format (format, args));
}
This will work:
[DllImport ("/System/Library/Frameworks/Foundation.framework/Foundation")]
static external void NSLog(IntPtr format, IntPtr arg1);
static void NSLog(string s)
{
NSString p1 = "%@";
NSString p2 = s;
NSLog(p1.NativePointer, p2.NativePointer);
}
I brought @Ck.'s answer up to date a bit:
[DllImport ("/System/Library/Frameworks/Foundation.framework/Foundation")]
public extern static void NSLog (IntPtr format, IntPtr arg1);
static void NSLog (string s)
{
NSString p1 = new NSString ("%@");
NSString p2 = new NSString (s);
NSLog (p1.Handle, p2.Handle);
}
I'm answering from an Objective-C/Cocoa background, with no monotouch experience, but I suspect you're having the issue because your monotouch string isn't a native NSString, but that's what you're telling NSLog to look for.
From some quick research, it looks like monotouch may have support to implicitly cast between its strings and NSString, but those wouldn't be triggered here since the arguments to NSLog are untyped.
Try casting "Hello World" to an NSString before calling NSLog, or else try changing the format argument from %@
(NSObject) to %s
(C-Style String).
精彩评论