gpt4 book ai didi

c# - 在 Linux 64 位上按值将结构传递给 P/Invoked 库?

转载 作者:IT王子 更新时间:2023-10-29 01:27:07 25 4
gpt4 key购买 nike

我正在尝试获取用于在 Linux x86_64 上编译的 C# 库的 native 依赖项。代码本身与平台无关并且易于编译。

但是,在第一次尝试使用已编译的依赖项在 Linux 上运行我的项目后,我开始从库中得到奇怪的结果,随后出现段错误。经过一些调查后,P/Invoke 函数的参数似乎没有以正确的顺序传递。看起来好像它们正在向后传递。

我尝试过以几种不同的方式编译 native 依赖项并明确定义不同的调用约定。似乎没有任何效果。

C# 外部方法定义

[DllImport(InteropUtil.PLATFORM_DLL)]
public static extern NavStatus dtqFindPath(IntPtr query
, NavmeshPoint startPosition
, NavmeshPoint endPosition
, IntPtr filter
, [In, Out] uint[] resultPath
, ref int pathCount
, int maxPath);

相关C++定义

#if _MSC_VER    // TRUE for Microsoft compiler.
#define EXPORT_API __declspec(dllexport) // Required for VC++
#else
#define EXPORT_API // Otherwise don't define.
#endif

extern "C"
{

EXPORT_API dtStatus dtqFindPath(dtNavMeshQuery* query
, rcnNavmeshPoint startPos
, rcnNavmeshPoint endPos
, const dtQueryFilter* filter
, dtPolyRef* path
, int* pathCount
, const int maxPath)
{
return query->findPath(startPos.polyRef
, endPos.polyRef
, &startPos.point[0]
, &endPos.point[0]
, filter
, path
, pathCount
, maxPath);
}
}

g++ 编译器设置

g++ -shared -o cai-nav-rcn.so.1 -g -fPIC -I Detour/Include -I DetourCrowd/Include -I Nav/Include Detour/Source/*.cpp DetourCrowd/Source/*.cpp Nav/Source/*.cpp

在下面的输出中,dtqFindPath 行清楚地显示了乱序参数。 maxPath 应为 100 (0x64),但实际为 1298。 1298 是 startPos 结构中的第一个 int。 100 是 path 的值。

部分 GDB 输出

Thread 1 (Thread 0x7fef64330740 (LWP 3923)):
#0 0x00007fef63823ce9 in waitpid () from /usr/lib/libpthread.so.0
#1 0x00000000004ae448 in ?? ()
#2 0x0000000000503b8b in ?? ()
#3 0x00000000004226b2 in ?? ()
#4 <signal handler called>
#5 0x00007feef052339c in dtNavMeshQuery::findPath (this=0x5405610, startRef=88101520, endRef=4203419680, startPos=0x7fff5fd3975c, endPos=0x7fff5fd3974c, filter=0x7fef64176ec0, path=0x64, pathCount=0x44d6595341be38e0, maxPath=1298) at Detour/Source/DetourNavMeshQuery.cpp:958
#6 0x00007feef0534d19 in dtqFindPath (query=0x5405610, startPos=..., endPos=..., filter=0x7fef64176ec0, path=0x64, pathCount=0x44d6595341be38e0, maxPath=1298) at Nav/Source/DetourNavMeshQueryEx.cpp:234
#7 0x0000000041ec2140 in ?? ()
...
#17 0x0000000005405610 in ?? ()
#18 0x0000000000000000 in ?? ()

我已经比较了两端的rcnNavmeshPointNavmeshPoint 结构体的大小,它们是相同的。进入 P/Invoke 调用的参数顺序正确,已使用调试器进行检查。

不妨包括我正在尝试使用的库是 CritterAI .

所以我的问题是:我应该更改什么以使这两段代码之间的调用约定匹配?


更新

我隔离了这个问题。这是未正确传递的结构。我创建了一个 SSCCE 来证明这一点:

互操作.cpp

#include <cstdio>

#if _MSC_VER
#define EXPORT_API __declspec(dllexport)
#else
#define EXPORT_API
#endif

struct s
{
unsigned int a;
float b[3];
};

extern "C"
{
EXPORT_API void testStruct(s str)
{
printf("STRUCT NATIVE\n");
printf("SIZE: %u\n", sizeof(s));
printf("%u, (%f, %f, %f)\n", str.a, str.b[0], str.b[1], str.b[2]);
}
}

cs.cs

using System;
using System.Runtime.InteropServices;

namespace InteropTest
{
[StructLayout(LayoutKind.Sequential)]
public struct v
{
public float X;
public float Y;
public float Z;
}

[StructLayout(LayoutKind.Sequential)]
public struct s
{
public uint A;
public v B;
}

public class Test
{
[DllImport("./test.so")]
public static extern void testStruct(s str);

unsafe static void Main(string[] args)
{
s mStr;
mStr.A = 22;
mStr.B.X = 33f;
mStr.B.Y = 44f;
mStr.B.Z = 55f;
Console.WriteLine("STRUCT MANAGED");
Console.WriteLine("SIZE: " + sizeof(s));
Console.WriteLine(mStr.A + ", (" + mStr.B.X + ", " + mStr.B.Y + ", " + mStr.B.Z + ")");
testStruct(mStr);
}
}
}

编译为

g++ -shared -o test.so -g -fPIC interop.cpp && mcs /unsafe cs.cs && ./cs.exe

我系统上的输出

STRUCT MANAGED
SIZE: 16
22, (33, 44, 55)
STRUCT NATIVE
SIZE: 16
22, (33.000000, 0.000000, 3.179688)

一些其他测试显示结构被“跳过”,其中打印 str.a 将打印出下一个非结构参数的值。该结构的其余部分似乎是垃圾。

最佳答案

注意:下面的答案针对的是问题的原始版本。

Linux x86_64 上只有一种调用约定。它被称为 System V AMD64 ABI .无论不匹配是什么,它肯定不在调用约定中。可能结构声明不匹配,或者存在我们看不到的其他错误。

我接下来要做的事情是,站在您的角度,编写一些简单的测试代码。我会编写一个 C++ 函数来接收一对 int 参数。检查它们是否以正确的顺序通过。说服自己调用约定不是问题所在,然后深入挖掘以找出问题的真正原因。

关于c# - 在 Linux 64 位上按值将结构传递给 P/Invoked 库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17331418/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com