获取结构的地址

时间:2017-10-12 10:24:30

标签: c# unity3d dll dllimport

这是我的代码:

int traffic_import_osm()

这是来自dll C库。函数TrafficRoadSystem* trafficRoadSystem;作为参考在void Update()对象上运行,我希望能够访问Error CS0212 You can only take the address of an unfixed expression inside of a fixed statement initializer中的对象。这在一个函数中运行良好,但我无法获取类变量的地址,我得到错误

results = traffic_import_osm(osmPath, &trafficRoadSystem);

TrafficRoadSystem trafficRoadSystem; void Start() { unsafe { string osmPath = "Assets/Resources/map.osm.pbf"; CarMove carMove = new CarMove(); int results; fixed( TrafficRoadSystem* ptr = &carMove.trafficRoadSystem) { results = traffic_import_osm(osmPath, &ptr); } } }

我尝试使用此解决方案 https://msdn.microsoft.com/en-us/library/29ak9b70(v=vs.90).aspx

我写了这个:

CS0459 Cannot take the address of a read-only local variable

我得到了错误results = traffic_import_osm(osmPath, &ptr); Preferences => File Types

2 个答案:

答案 0 :(得分:5)

在Unity中制作C或C ++插件需要对这些语言有广泛的了解。这意味着在尝试在Unity中使用原始指针之前,您应该花时间学习指针。因为即使你编译它,你也可能遇到很难修复崩溃。

你有:

unsafe TrafficRoadSystem* trafficRoadSystem;

并希望将其传递给下面的函数:

public unsafe static extern int traffic_import_osm(..., TrafficRoadSystem** out_road_system);

1 trafficRoadSystem变量是指针,您需要创建另一个指向trafficRoadSystem的指针。这称为“指针指针”

TrafficRoadSystem** addressOfTrafficRoadSystem = &trafficRoadSystem;

注意双“**”。

2 。您必须使用fixed关键字来执行我在#1中提到的内容。

fixed (TrafficRoadSystem** addressOfTrafficRoadSystem = &trafficRoadSystem)
{

}

3 。您可以将指针传递给traffic_import_osm函数的指针地址。

全新的Start功能:

void Start()
{
    unsafe
    {
        fixed (TrafficRoadSystem** addressOfTrafficRoadSystem = &trafficRoadSystem)
        {
            string osmPath = "Assets/Resources/map.osm.pbf";
            int results;
            results = traffic_import_osm(osmPath, addressOfTrafficRoadSystem);
        }
    }
}

无关的未来可能的问题:

1 。我注意到您在更新的问题中做了CarMove carMove = new CarMove();。此处不要使用new关键字,因为CarMove继承自MonoBehaviour。有关如何操作,请参阅this答案。

2 。我还注意到您使用了"Assets/Resources/map.osm.pbf";。构建项目时,此路径无效。请考虑使用 StreamingAssets 文件夹而不是仅适用于Resources API的Resources文件夹。您将Application.streamingAssetsPath StreamingAssets 文件夹一起使用。

答案 1 :(得分:1)

使用原始指针的替代方法是使用编组。编组允许您使用C#数据结构并将其转换为C可理解的数据,而无需任何不安全的关键字。

Mono有document描述如何使用 PInvoke (这是您正在寻找的搜索字词)与本地库进行正确交互。

Hereherehere您还可以找到PInvoke和编组的介绍。

基本上,您将指针签名替换为IntPtr - 类型,这是指针的托管版本。要转换托管结构变量,首先需要分配一个内存区域并将其用于结构

IntPtr ptr;
TrafficRoadSystem _struct;
try {
    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(_struct));
    Marshal.StructureToPtr(_struct, ptr, false);
} finally {
    Marshal.FreeHGlobal(ptr);
}

我不知道如何正确处理双指针..