从 C 调用 Mono exe 找不到 libc
Calling Mono exe from C does not find libc
在 Ubuntu 中,我使用 Mono (v3.2.8) 和嵌入式 Mono 运行time 从 C 调用 C# 可执行文件。当我从命令行(即 mono testFile.exe)调用 exe (.NET 4.5) 时,它工作正常。但是,当我 运行 我的 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");
查看调用堆栈和单声道源代码,我认为失败与调用 libc.so 中的本机 'uname' 函数有关(CheckOS() 函数,第 50 行mcs/class/System/System/Platform.cs):
if (uname (buf) == 0) {
我认为发生的事情是 p/Invoke 图层无法定位 libc.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);
}
我的 C# 代码:
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搜索顺序,发现调用成功的顺序和调用不成功的完全不一样。所以它正在搜索,只是不是很好。然后我将 libc.so.6 复制到当前目录,重命名为 libc.so,然后将 LD_LIBRARY_PATH 设置到同一位置。这给了我成功。我现在让我的 Linux 大师研究如何使这个解决方案更 'correct',但至少我有一个 运行ning 程序。 This 可能与我的问题相同(尽管该解决方案对我不起作用)。
问题是您缺少 dll 映射 (mono_config_parse)。以下将使用单声道 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/mono/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
根据您的更新,应用程序似乎正在搜索 libc.so 而不是 libc.so.6。您通过手动将 LD_LIBRARY_PATH 指向具有您复制的 libc.so 的当前文件夹来使其工作。
建议:请求您的 Linux 大师将 libc.so 符号链接到 libc.so.6,以便您的应用程序正常工作。
我也 运行 关注这个问题。我注意到 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 除外。
希望对大家有所帮助!
在 Ubuntu 中,我使用 Mono (v3.2.8) 和嵌入式 Mono 运行time 从 C 调用 C# 可执行文件。当我从命令行(即 mono testFile.exe)调用 exe (.NET 4.5) 时,它工作正常。但是,当我 运行 我的 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");
查看调用堆栈和单声道源代码,我认为失败与调用 libc.so 中的本机 'uname' 函数有关(CheckOS() 函数,第 50 行mcs/class/System/System/Platform.cs):
if (uname (buf) == 0) {
我认为发生的事情是 p/Invoke 图层无法定位 libc.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);
}
我的 C# 代码:
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搜索顺序,发现调用成功的顺序和调用不成功的完全不一样。所以它正在搜索,只是不是很好。然后我将 libc.so.6 复制到当前目录,重命名为 libc.so,然后将 LD_LIBRARY_PATH 设置到同一位置。这给了我成功。我现在让我的 Linux 大师研究如何使这个解决方案更 'correct',但至少我有一个 运行ning 程序。 This 可能与我的问题相同(尽管该解决方案对我不起作用)。
问题是您缺少 dll 映射 (mono_config_parse)。以下将使用单声道 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/mono/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
根据您的更新,应用程序似乎正在搜索 libc.so 而不是 libc.so.6。您通过手动将 LD_LIBRARY_PATH 指向具有您复制的 libc.so 的当前文件夹来使其工作。
建议:请求您的 Linux 大师将 libc.so 符号链接到 libc.so.6,以便您的应用程序正常工作。
我也 运行 关注这个问题。我注意到 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 除外。
希望对大家有所帮助!