You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从C#调用带引用参数的C++函数?代码方案验证问询

能否通过给定C#代码调用C++函数并获取正确的min.x值?

C++ 原代码

struct Vector3f
{
    float x;
    float y;
    float z;
};

void getLocalBounds(BoxShape* boxShape, Vector3f& min, Vector3f& max)
{
   min.x = 3;
}

请问是否可以通过如下C#代码调用上述C++函数,并获取到min.x的值为3?

C# 调用代码

[StructLayout(LayoutKind.Sequential)]
public struct Vector3f
{
    public float x;
    public float y;
    public float z;
}

[DllImport("a.lib", EntryPoint = "getLocalBounds", CallingConvention = CallingConvention.Cdecl)]
public static void getLocalBounds(IntPtr boxShapePtr, ref Vector3f min, ref Vector3f max);

public void Test()
{
   IntPtr boxShapePtr = null; // 假设已正确构造有效指针
   Vector3f a, b;
   a.x = 100;
   getLocalBounds(boxShapePtr, ref a, ref b);

   Assert(a.x == 3); // 假设C++函数已赋值a.x
}

注:Vector3f getBoundMin();这种方式可行,但它是基于栈传值而非栈传引用。


可以实现,但需要满足几个关键前提:

  • 修正DllImport的库路径:C#的DllImport不能直接引用.lib静态库,Windows下需改为a.dll,Linux/macOS下改为liba.so/liba.dylib,同时要确保C++代码已编译为对应的动态链接库
  • 保证结构体内存布局一致:C#中Vector3f标注了[StructLayout(LayoutKind.Sequential)],和C++结构体的默认顺序布局完全匹配,三个float成员的内存排列、大小都一致,这是数据正确传递的基础
  • 匹配调用约定:C++函数在GCC编译器下默认使用cdecl调用约定,C#代码中指定了CallingConvention.Cdecl,两者匹配才能保证参数栈的正确处理
  • 确保函数导出名称正确:如果C函数没有添加extern "C"修饰,编译后会被C名字修饰,此时EntryPoint指定的getLocalBounds会找不到函数。需要给C++函数加上extern "C"来导出原始名称:
    extern "C" void getLocalBounds(BoxShape* boxShape, Vector3f& min, Vector3f& max)
    {
       min.x = 3;
    }
    

当以上条件都满足时,C#中通过ref传递Vector3f结构体,对应C的引用传递(本质都是传递内存地址),C函数修改min.x的操作会直接作用到C#变量a的内存上,Assert(a.x == 3)会成立。


内容的提问来源于stack exchange,提问作者216 dark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 13:29:28