从C调用Mono exe找不到libc



在Ubuntu中,我使用Mono (v3.2.8)和嵌入式Mono运行时从C调用c#可执行文件。当我调用exe(。. NET 4.5)从命令行(即,mono testFile.exe),它工作得很好。然而,当我运行我的C测试程序时,它抛出了一个c#异常:

libc at   at (wrapper managed-to-native) System.Platform:uname (intptr)
  at System.Platform.get_IsMacOS () [0x00000] in <filename unknown>:0
  at System.Net.WebRequest.GetSystemWebProxy () [0x00000] in <filename unknown>:0
  at System.Net.WebRequest.GetDefaultWebProxy () [0x00000] in <filename unknown>:0
  at System.Net.WebRequest.get_DefaultWebProxy () [0x00000] in <filename unknown>:0
  at System.Net.GlobalProxySelection.get_Select () [0x00000] in <filename unknown>:0
  at System.Net.HttpWebRequest..ctor (System.Uri uri) [0x00000] in <filename unknown>:0
  at (wrapper remoting-invoke-with-check) System.Net.HttpWebRequest:.ctor (System.Uri)
  at System.Net.HttpRequestCreator.Create (System.Uri uri) [0x00000] in <filename unknown>:0
  at System.Net.WebRequest.Create (System.Uri requestUri) [0x00000] in <filename unknown>:0
  at System.Net.WebRequest.Create (System.String requestUriString) [0x00000] in <filename unknown>:0
  at MyClass.MainClass.Main (System.String[] args) [0x00000] in <filename unknown>:0

我把它缩小到这一行代码:

WebRequest request = WebRequest.Create("http://www.google.com");

查看调用堆栈和mono源代码,我认为失败与libc中本机'uname'函数的调用有关。so (CheckOS()函数,mcs/class/System/System/Platform.cs第50行):

if (uname (buf) == 0) {

我认为发生的事情是p/Invoke层无法找到lib .so。然而,当我在可执行文件的Main()函数中进行相同的调用时,它执行得很好,我很困惑为什么它在一个地方工作而不是另一个地方。同样奇怪的是,异常消息不是DllNotFoundException,而是这个通用的"libc"消息(尽管我已经确认,当我尝试使用伪造的so .调用p/Invoke时,我得到了相同的消息)。

我的C代码:
int main(int argc,const char* argv[]) {
    MonoDomain* domain=mono_jit_init("testFile.exe");
    MonoAssembly* assembly=mono_domain_assembly_open(domain,"testFile.exe");
    MonoImage* image=mono_assembly_get_image(assembly);
    const char* args[1];
    args[0]="testFile.exe";
    mono_jit_exec(domain,assembly,1,(char**) args);
}

My c# code:

namespace MyClass {
    class MainClass {
        public static void Main (string[] args) {
            WebRequest request=WebRequest.Create("http://www.google.com");
        }
    }
}

gcc编译选项为:

gcc cTest.c -I/usr/include/mono-2.0 -DREENTRANT -lmono-2.0 -lm -lrt -ldl -lpthread

单编译选项有:

dmcs -out:testFile.exe -platform:anycpu -sdk:4.5 -target:exe -unsafe+ -main:MyClass.MainClass -reference:System,System.Configuration,System.Data,System.ServiceModel,System.Web,System.Xml *.cs

更新:我使用MONO_LOG_LEVEL和MONO_LOG_MASK来跟踪.so搜索序列,发现成功调用的序列与不成功调用的序列完全不同。所以它在搜索,只是不是很好。然后我复制了我的lib .so。6到当前目录,重命名为libc。so,然后将LD_LIBRARY_PATH设置为相同的位置。这给了我成功。我现在让我的Linux专家研究如何使这个解决方案更"正确",但至少我有一个运行的程序。这可能与我的问题相同(尽管解决方案不适合我)。

问题是您缺少dll映射(mono_config_parse)。下面将使用mono 3。X和4。X嵌入和避免libc错误。

#include <mono/jit/jit.h>
#include <mono/metadata/environment.h>
#include <stdlib.h>
int 
main(int argc, char* argv[]) {
    MonoDomain *domain;
    const char *file;
    int retval;
    mono_config_parse (NULL);
    domain = mono_jit_init ("textFile.exe");
    MonoAssembly *assembly;
    assembly = mono_domain_assembly_open (domain, "testFile.exe");
    mono_jit_exec (domain, assembly, argc, argv);
    retval = mono_environment_exitcode_get ();      
    mono_jit_cleanup (domain);
    return retval;
}

运行时的某些功能,如Dll重新映射依赖于配置文件,加载配置文件,只需添加:

mono_config_parse (NULL);

将加载Mono配置文件(通常是/etc/mon/config)。http://www.mono-project.com/docs/advanced/embedding

供参考:在Ubuntu 15.04上,我使用:

gcc main.c `pkg-config --cflags --libs mono-2`

你当然可以更新它来抓取mono-sgen和boehm jit。

OS-X:

gcc main.c -m32 -framework Foundation -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk 
 -lmonosgen-2.0 
 -I/Library/Frameworks/Mono.framework/Headers/mono-2.0 
 -L/Library/Frameworks/Mono.framework/Libraries

我也遇到过这个问题。我注意到的是,mkbundle输出列出了它嵌入的程序集,而System.Net.dll不包括在内。在mkbundle命令行上手动添加后,一切正常。

我现在使用的命令行:

mkbundle my.exe --deps --keeptemp --static --config /etc/mono/configlibc --machine-config /etc/mono/4.5/machine.config System.Net.dll -o bssetup.exe

configlibc文件是该目录下默认配置文件的修改副本。修改是删除所有的映射行,除了libc的映射行。

希望对大家有所帮助!

根据您的更新,看起来应用程序正在搜索libc。所以不是libc。So。6。通过手动将LD_LIBRARY_PATH指向具有libc的当前文件夹,可以使其正常工作。这样你就复制了。

建议:让你的Linux大师符号链接libc。所以,对我来说。

相关内容

最新更新