我使用了这个 dotnet 托管示例中的代码并遇到了一些问题。
这就是我获取函数指针的方式:
component_entry_point_fn function = nullptr;
int rc = functionPointer(
dllPath.c_str(),
dotnetType.c_str(),
methodName.c_str(),
nullptr,
nullptr,
(void**)&function);
然后我称它为:
struct test {
const char* str = "from host!";
int i = 1;
} testArgs;
function(&testArgs, sizeof(testArgs));
而且效果很好。输出:
Hello, world! from Lib [count: 1]
-- message: from host!
-- number: 1
Hello again, world! from Lib [count: 2]
-- message: from host!
-- number: 1
但是当我尝试将参数作为元组传递时:
std::tuple<FunctionArgs...> argsTuple = std::make_tuple(args...);
function(&argsTuple, sizeof(argsTuple));
我明白了:
Hello, world! from Lib [count: 1]
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.SpanHelpers.IndexOfNullByte(Byte*)
at System.Runtime.InteropServices.Marshal.PtrToStringUTF8(IntPtr)
at Scripts.Lib.PrintLibArgs(LibArgs)
at Scripts.Lib.HelloAgain(IntPtr, Int32)
C# 端的代码与上面链接中的示例相同。 另一个重要的事实是,在 Arm MacOS 上一切正常,没有错误。该错误出现在 Linux x86_64 上。编译器到处都是一样的:clang。
结构和元组的 sizeof 相同 - 16 字节。 尝试添加对齐:
alignas(16) std::tuple<FunctionArgs...>
argsTuple = std::make_tuple(args...);
gcc 和 clang 似乎都交换了内存中元组元素的顺序 https://godbolt.org/z/PaqaqcqTn,但这是一个实现细节,而不是您可以在代码中依赖的东西。
您不应该跨 C 接口传递 C++ 元组。