非托pipeC#调用静态库

我正在使用swig来生成一些C#代码库的基础上使用C#的包装。 当我运行swig时,它会生成一个包装器的c文件,将所有的function公开给生成的PInvoke C#文件…例如:

// This is in KodLogic_wrap.c SWIGEXPORT void SWIGSTDCALL CSharp_DMGameMode_timeLimit_set(void * jarg1, unsigned short jarg2) { ... } 

 // This is in KodLogicPInvoke.cs [global::System.Runtime.InteropServices.DllImport("KodLogic", EntryPoint="CSharp_DMGameMode_timeLimit_set")] 

当我构build一个dynamic库时,这很好用。 不过,我现在需要支持iOS,所以我准备了一个静态库,并通过-dllimport '__Internal'选项来-dllimport '__Internal'工作。

不幸的是,我得到的链接错误,如:

 "_DMGameMode_timeLimit_set", referenced from: RegisterMonoModules() in RegisterMonoModules.o (maybe you meant: _CSharp_DMGameMode_timeLimit_set) 

的确,我的意思是“CSharp_DMGameMode_timeLimit_set”,但这是“入口点”参数的一点?

所以,由于这个错误是由Unity生成的Xcode项目抛出的,我不太确定失败的根源是什么。 它是否对静态库失败? 这是一个固定的统一或边上的东西?

更新:在深入挖掘之后,我想我对这里发生的事情有一点点的了解。

主要的问题似乎来自AOT编译器,它试图将所有CS代码编译到ARM程序集。 这似乎是iOS所需要的,所以在Unity的AOT编译期间,它会生成一个文件RegisterMonoModules.cpp ,它试图为本地代码定义访问函数。 RegisterMonoModules.cpp不尊重入口点参数,导致未定义的符号错误被抛出…

仍试图find一个适当的解决方法。

主要问题似乎来自统一,而不是Swig和Mono。 如上所述,Unity执行不支持入口点参数的AOT编译。 这会产生调用函数名称的cpp代码,而不是入口点名称。

我已经通过将脚本后端切换到IL2cpp来确认了这一点,并且入口点名称在那里得到了证实。


让我们切换到callback。 不完全相关的问题,但它绝对适合Unity +原生插件+ iOS的上下文。

AFAIK,你不能在iOS上使用Mono 2x编组托pipe方法。 我以前不得不从Swig生成的文件中删除所有的stringcallback和exception处理程序。 幸运的是,经过一些调整,IL2Cpp支持callback:

  1. using AOT;添加using AOT;
  2. [MonoPInvokeCallback(typeof(method_signature))]装饰callback

你可以使用这个脚本,只用它来处理生成的swig文件:

 def process_csharp_callbacks(pinvoke_file): """Process PInvoke file by fixing the decorators for callback methods to use: [MonoPInvokeCallback(typeof(method_signature))] """ # prepare requirements with open(pinvoke_file) as f: content = f.read() callback_methods_regex = re.compile(r"( +)static (?:void|string) (?:SetPending|CreateString)\w*\([\s\w\,]+\)") callback_decorator = "[MonoPInvokeCallback(typeof(ExceptionDelegate))]" callback_arg_decorator = "[MonoPInvokeCallback(typeof(ExceptionArgumentDelegate))]" callback_str_decorator = "[MonoPInvokeCallback(typeof(SWIGStringDelegate))]" # add use AOT content = content.replace("\n\n", "\nusing AOT;\n", 1) # fix callback methods def method_processor(match): match_string = match.group() indentation = match.captures(1)[0] if match_string.find(",") != -1: fix = callback_arg_decorator elif match_string.find("static string") != -1: fix = callback_str_decorator else: fix = callback_decorator return indentation + fix + "\n" + match_string content = callback_methods_regex.sub(method_processor, content) # write it back with open(pinvoke_file, "w+") as f: f.write(content) 

对于任何正在寻找帮助将其生成的swig CSharp PInvoke文件转换为单声道2x脚本后端将允许的内容的帮助,请在生成CSharp文件之后将其粘贴到构build过程的某个位置:

 pinvoke_template = """{extern_prefix} CSharp_{method_signature}; {normal_prefix} {method_signature} {{ {return_statement}CSharp_{method_name}({method_args}); }}""" def process_csharp_wrapper(csharp_dir): """Reads the PINVOKE csharp file, and performs the following: 1. Remove EntryPoint="xxx" from the decorators 2. Make the methods match their native counterpart name 3. Add a C# method with the original name, for compatability """ # prepare requirements pinvoke_file = os.path.join(csharp_dir, "KodLogicPINVOKE.cs") with open(pinvoke_file) as f: content = f.read() decorator_regex = re.compile(r', EntryPoint=".*?"') method_regex = re.compile(r"(public static extern \w+[\w:\.]+)\s(([^S]\w+)\((?:([\w:\. ]+)\,?)*\));") # fix decorators content = decorator_regex.sub("", content) # fix method definitions def method_processor(match): extern_prefix = match.captures(1)[0] return pinvoke_template.format( extern_prefix=extern_prefix, normal_prefix=extern_prefix.replace("extern ", ""), method_signature=match.captures(2)[0], return_statement=("return " if extern_prefix.find("void") == -1 else ""), method_name=match.captures(3)[0], method_args=", ".join(map(lambda s: s.strip().split()[1], match.captures(4))) ) content = method_regex.sub(method_processor, content) # write it back with open(pinvoke_file, "w+") as f: f.write(content)