Unity與c++ 結構體中帶陣列引數傳遞
阿新 • • 發佈:2019-01-27
在unity與c++ 進行互動中往往會有結構體的資料傳遞,如果在結構體中定義了陣列,那麼在unity中需要怎樣去定義結構體從而對應c++中定義的帶有陣列的結構體呢.
請看程式碼:
在c++程式碼中定義了一個結構體,結構體中還定義了兩個陣列物件。那麼c#該怎樣定義呢#ifndef TRACK_H_H_ #define TRACK_H_H_ #define TRACK_POINT_SIZE 68 #define TRACK_MOUNT_POINT_SIZE 11 #ifdef __cplusplus extern "C" { #endif typedef struct TrackPointCoord{ float x; float y; }TrackPointCoord; typedef struct TRACK2DRET{ TrackPointCoord allTrackPoints[TRACK_POINT_SIZE]; TrackPointCoord mountTrackPoints[TRACK_MOUNT_POINT_SIZE]; float scale; float angle; float rendering_paramsy; float rendering_paramsx; }TRACK2DRET; bool Track2DForUnity3D(unsigned char* rgba, TRACK2DRET* track2dRet); #ifdef __cplusplus } #endif #endif
請看程式碼:
using System.Runtime.InteropServices; using UnityEngine; public struct TrackPointCoord { public float x; public float y; public TrackPointCoord(float _x, float _y) { this.x = _x; this.y = _y; } }; public struct TRACK2DRET { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 68)] public TrackPointCoord[] allTrackPoints; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public TrackPointCoord[] mountTrackPoints; public float scale; public float angle; public float rendering_paramsy; public float rendering_paramsx; public TRACK2DRET(TrackPointCoord[] _allTrackPoints, TrackPointCoord[] _mountTrackPoints, float _scale, float _angle, float _rendering_paramsy, float _rendering_paramsx) { this.allTrackPoints = _allTrackPoints; this.mountTrackPoints = _mountTrackPoints; this.scale = _scale; this.angle = _angle; this.rendering_paramsy = _rendering_paramsy; this.rendering_paramsx = _rendering_paramsx; } }; public class TrackTool: Manager { #region Android #if UNITY_ANDROID [DllImport("TrackToolForUnity3D")] private static extern bool Track2DForUnity3D(byte[] rgba, ref TRACK2DRET track2dRet); #endif #endregion /// <summary> /// 初始化結構體 /// </summary> public TRACK2DRET InitStruct() { TrackPointCoord[] _allTrackPoints, _mountTrackPoints; TrackPointCoord _TrackPointCoord = new TrackPointCoord(0, 0); _allTrackPoints = new TrackPointCoord[68]; _mountTrackPoints = new TrackPointCoord[11]; for (int i = 0; i < _allTrackPoints.Length; i++) { _allTrackPoints[i] = _TrackPointCoord; } for (int i = 0; i < _mountTrackPoints.Length; i++) { _mountTrackPoints[i] = _TrackPointCoord; } TRACK2DRET track2dret = new TRACK2DRET(_allTrackPoints, _mountTrackPoints, 0, 0, 0, 0); return track2dret; }
在c# 可以看到//呼叫so public bool GetTarck2d(Color32[] Pixels,ref TRACK2DRET track2dret) { return Track2DForUnity3D(Color32ArrayToByteArray(Pixels), ref track2dret); } /// <summary> /// color32 array to byte array /// </summary> /// <param name="colors"></param> /// <returns></returns> byte[] Color32ArrayToByteArray(Color32[] colors) { if (colors == null || colors.Length == 0) return null; int length = Marshal.SizeOf(typeof(Color32)) * colors.Length; byte[] bytes = new byte[length]; GCHandle handle = default(GCHandle); try { handle = GCHandle.Alloc(colors, GCHandleType.Pinned); Marshal.Copy(handle.AddrOfPinnedObject(), bytes, 0, length); } finally { if (handle != default(GCHandle)) handle.Free(); } return bytes; } }
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 68)]
MarshalAs屬性指示如何在託管程式碼和非託管程式碼之間封送資料[MarshalAs(UnmanagedType unmanagedType, 命名引數)]
實際上相當於構造一個MarshalAsAttribute類的物件
常用的UnmanagedType列舉值:
BStr 長度字首為雙位元組的 Unicode 字串;
LPStr 單位元組、空終止的 ANSI 字串。;
LPWStr 一個 2 位元組、空終止的 Unicode 字串;
ByValArray用於在結構中出現的內聯定長字元陣列,應始終使用MarshalAsAttribute的SizeConst欄位來指示陣列的大小。
SizeConst值對應著c++中定義的結構體中陣列大小.。
-----------------------》
在c#中想要獲取c++中返回的結構體值需要使用ref方法。
[DllImport("TrackToolForUnity3D")]
private static extern bool Track2DForUnity3D(byte[] rgba, ref TRACK2DRET track2dRet);
c++中:
bool Track2DForUnity3D(unsigned char* rgba, TRACK2DRET* track2dRet);
-----------------------------》
說下unsigned char* rgba引數
在c# 中需要定義物件為byte[]形式進行傳值。上面程式碼中提供一個簡便的將Color32[]轉為byte[]方法。