I’m trying to call Unity C# script from the Objective-C side. Functions with void parameters work. Functions with string parameters work if the script on the other side is Javascript.
Functions with string parameters crash if the script on the other side is C#. The crash is a BAD_EXEC.
I’m fairly sure I’m not correctly marshalling parameters correctly. There really isn’t too much documentation about this on the web.
I’ve read Embedding Mono and I’ve looked at the really old examples on Github.
http://www.mono-project.com/Embedding_Mono
https://github.com/mono/mono/tree/master/samples/embed
Types and functions are declared as such:
typedef void* MonoDomain;
typedef void* MonoAssembly;
typedef void* MonoImage;
typedef void* MonoClass;
typedef void* MonoObject;
typedef void* MonoMethodDesc;
typedef void* MonoMethod;
typedef void* MonoString;
typedef int gboolean;
MonoDomain* mono_domain_get();
MonoAssembly* mono_domain_assembly_open(MonoDomain* domain, const char *assemblyName);
MonoImage* mono_assembly_get_image(MonoAssembly* assembly);
MonoMethodDesc* mono_method_desc_new(const char* methodString, gboolean useNamespace);
MonoMethodDesc* mono_method_desc_free(MonoMethodDesc* desc);
MonoMethod* mono_method_desc_search_in_image(MonoMethodDesc* methodDesc, MonoImage* image);
MonoObject* mono_runtime_invoke(MonoMethod* method, void* obj, void** params, MonoObject** exc);
MonoClass* mono_class_from_name (MonoImage *image, const char* name_space, const char *name);
MonoString* mono_string_new(MonoDomain* domain, const char* str);
Then variables are declared:
@interface UnityObject : NSObject
{
MonoDomain* domain;
NSString* assemblyPath;
MonoAssembly* monoAssembly;
MonoImage* monoImage;
MonoMethodDesc* runChallengeDesc;
MonoMethod* runChallengeMethod;
}
@end
And then in init:
- (id)init
{
if ((self = [super init]))
{
assemblyPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Data/Managed/Assembly-CSharp-firstpass.dll"];
domain = mono_domain_get();
monoAssembly = mono_domain_assembly_open(domain, assemblyPath.UTF8String);
monoImage = mono_assembly_get_image(monoAssembly);
runChallengeDesc = mono_method_desc_new("Marshal:RunChallenge(string)", FALSE);
runChallengeMethod = mono_method_desc_search_in_image(runChallengeDesc, monoImage);
mono_method_desc_free(runChallengeDesc);
}
return self;
}
The above all works as expected.
Then the method is called:
NSString *msg = @"Some message string";
MonoString *str = mono_string_new(domain, msg.UTF8String);
void *args[1];
args[0] = &str;
if (runChallengeMethod)
mono_runtime_invoke(runChallengeMethod, NULL, args, NULL);
I’m fairly sure I’m not correctly marshalling parameters correctly. The crash is a BAD_EXEC.
I’d advise you to elaborate a little more on the code you posted. With the code you posted, assuming that the “…” is implemented correctly, you are executing a static method with 1 parameter that is undefined.
You at least need to do this instead:
I can only guess that the transcription from your real code to this question was done poorly as almost 0 of the code you posted is valid.
The code at http://www.mono-project.com/Embedding_Mono#Creating_objects shows how to pass Mono Strings when they are not out or by ref.