diff --git a/BMapBindings/BMapSharp/BMapSharp/BMap.cs b/BMapBindings/BMapSharp/BMapSharp/BMap.cs index acd700c..888d1b0 100644 --- a/BMapBindings/BMapSharp/BMapSharp/BMap.cs +++ b/BMapBindings/BMapSharp/BMapSharp/BMap.cs @@ -58,11 +58,11 @@ namespace BMapSharp { // the native memory we created is a simple array and each item is a pointer to a NULL-terminated UTF8 string. // Please note the array self is also NULL-terminated otherwise we don't know its length. - public nint MarshalManagedToNative(object ManagedObj) { + public IntPtr MarshalManagedToNative(object ManagedObj) { // Check marshaler type - if (!m_MarshalerType.HasFlag(MarshalerType.In)) return nint.Zero; + if (!m_MarshalerType.HasFlag(MarshalerType.In)) return IntPtr.Zero; // Check nullptr object. - if (ManagedObj is null) return nint.Zero; + if (ManagedObj is null) return IntPtr.Zero; // Check argument type. string[] castManagedObj = ManagedObj as string[]; if (castManagedObj is null) @@ -70,45 +70,45 @@ namespace BMapSharp { // Allocate string items first int szArrayItemCount = castManagedObj.Length; - int szArrayItemSize = Marshal.SizeOf(); - nint[] apString = new nint[szArrayItemCount]; + int szArrayItemSize = Marshal.SizeOf(); + IntPtr[] apString = new IntPtr[szArrayItemCount]; for (int i = 0; i < szArrayItemCount; ++i) { // Check null string string stringObj = castManagedObj[i]; - if (stringObj is null) apString[i] = nint.Zero; + if (stringObj is null) apString[i] = IntPtr.Zero; else apString[i] = BMStringMarshaler.ToNative(stringObj); } // Allocate array pointer now. - nint pArray = Marshal.AllocHGlobal(szArrayItemSize * (szArrayItemCount + 1)); + IntPtr pArray = Marshal.AllocHGlobal(szArrayItemSize * (szArrayItemCount + 1)); // Copy string pointer data Marshal.Copy(apString, 0, pArray, szArrayItemCount); // Setup NULL ternimal - Marshal.WriteIntPtr(pArray + (szArrayItemSize * szArrayItemCount), nint.Zero); + Marshal.WriteIntPtr(pArray + (szArrayItemSize * szArrayItemCount), IntPtr.Zero); // Return value return pArray; } - public object MarshalNativeToManaged(nint pNativeData) { + public object MarshalNativeToManaged(IntPtr pNativeData) { // Check marshaler type if (!m_MarshalerType.HasFlag(MarshalerType.Out)) return null; // Check nullptr - if (pNativeData == nint.Zero) return null; + if (pNativeData == IntPtr.Zero) return null; // Get the length of array int szArrayItemCount = BMStringArrayMarshaler.GetArrayLength(pNativeData); - int szArrayItemSize = Marshal.SizeOf(); + int szArrayItemSize = Marshal.SizeOf(); // Prepare array cache and read it. - nint[] apString = new nint[szArrayItemCount]; + IntPtr[] apString = new IntPtr[szArrayItemCount]; Marshal.Copy(pNativeData, apString, 0, szArrayItemCount); // Iterate the array and process each string one by one. string[] ret = new string[szArrayItemCount]; for (int i = 0; i < szArrayItemCount; ++i) { // Get string pointer - nint pString = apString[i]; - if (pString == nint.Zero) { + IntPtr pString = apString[i]; + if (pString == IntPtr.Zero) { ret[i] = null; continue; } @@ -120,25 +120,25 @@ namespace BMapSharp { return ret; } - public void CleanUpNativeData(nint pNativeData) { + public void CleanUpNativeData(IntPtr pNativeData) { // Check marshaler type if (!m_MarshalerType.HasFlag(MarshalerType.In)) return; // Check nullptr - if (pNativeData == nint.Zero) return; + if (pNativeData == IntPtr.Zero) return; // Get the length of array int szArrayItemCount = BMStringArrayMarshaler.GetArrayLength(pNativeData); - int szArrayItemSize = Marshal.SizeOf(); + int szArrayItemSize = Marshal.SizeOf(); // Prepare array cache and read it. - nint[] apString = new nint[szArrayItemCount]; + IntPtr[] apString = new IntPtr[szArrayItemCount]; Marshal.Copy(pNativeData, apString, 0, szArrayItemCount); // Free array self Marshal.FreeHGlobal(pNativeData); // Iterate the string pointer array and free them one by one. - foreach (nint pString in apString) { + foreach (IntPtr pString in apString) { // Free string pointer - if (pString == nint.Zero) continue; + if (pString == IntPtr.Zero) continue; Marshal.FreeHGlobal(pString); } } @@ -157,9 +157,9 @@ namespace BMapSharp { /// /// The pointer to array for checking. /// The length of array (NULL terminal exclusive). - internal static int GetArrayLength(nint ptr) { - int count = 0, unit = Marshal.SizeOf(); - while (Marshal.ReadIntPtr(ptr) != nint.Zero) { + internal static int GetArrayLength(IntPtr ptr) { + int count = 0, unit = Marshal.SizeOf(); + while (Marshal.ReadIntPtr(ptr) != IntPtr.Zero) { ptr += unit; ++count; } @@ -181,11 +181,11 @@ namespace BMapSharp { m_MarshalerType = marshaler_type; } - public nint MarshalManagedToNative(object ManagedObj) { + public IntPtr MarshalManagedToNative(object ManagedObj) { // Check marshaler type - if (!m_MarshalerType.HasFlag(MarshalerType.In)) return nint.Zero; + if (!m_MarshalerType.HasFlag(MarshalerType.In)) return IntPtr.Zero; // Check requirements. - if (ManagedObj is null) return nint.Zero; + if (ManagedObj is null) return IntPtr.Zero; string castManagedObj = ManagedObj as string; if (castManagedObj is null) throw new MarshalDirectiveException("BMStringMarshaler must be used on a string."); @@ -193,20 +193,20 @@ namespace BMapSharp { return BMStringMarshaler.ToNative(castManagedObj); } - public object MarshalNativeToManaged(nint pNativeData) { + public object MarshalNativeToManaged(IntPtr pNativeData) { // Check marshaler type if (!m_MarshalerType.HasFlag(MarshalerType.Out)) return null; // Check nullptr - if (pNativeData == nint.Zero) return null; + if (pNativeData == IntPtr.Zero) return null; // Call self return BMStringMarshaler.ToManaged(pNativeData); } - public void CleanUpNativeData(nint pNativeData) { + public void CleanUpNativeData(IntPtr pNativeData) { // Check marshaler type if (!m_MarshalerType.HasFlag(MarshalerType.In)) return; // Check nullptr - if (pNativeData == nint.Zero) return; + if (pNativeData == IntPtr.Zero) return; // Free native pointer Marshal.FreeHGlobal(pNativeData); } @@ -225,7 +225,7 @@ namespace BMapSharp { /// /// The pointer for checking. /// The length of C style string (NUL exclusive). - internal static int GetCStringLength(nint ptr) { + internal static int GetCStringLength(IntPtr ptr) { int count = 0, unit = Marshal.SizeOf(); while (Marshal.ReadByte(ptr) != (byte)0) { ptr += unit; @@ -240,13 +240,13 @@ namespace BMapSharp { /// /// String object. Caller must make sure this object is not null. /// The created native data pointer. - internal static nint ToNative(string obj) { + internal static IntPtr ToNative(string obj) { // Encode string first byte[] encString = Encoding.UTF8.GetBytes(obj); // Allocate string memory with extra NUL. int szStringItemCount = encString.Length; int szStringItemSize = Marshal.SizeOf(); - nint pString = Marshal.AllocHGlobal(szStringItemSize * (szStringItemCount + 1)); + IntPtr pString = Marshal.AllocHGlobal(szStringItemSize * (szStringItemCount + 1)); // Copy encoded string data Marshal.Copy(encString, 0, pString, szStringItemCount); // Setup NUL @@ -260,7 +260,7 @@ namespace BMapSharp { /// /// Native pointer holding string data. Caller must make sure this pointer is not nullptr. /// The extracted managed string data. - internal static string ToManaged(nint ptr) { + internal static string ToManaged(IntPtr ptr) { // Get the length of given string. int szStringItemCount = BMStringMarshaler.GetCStringLength(ptr); int szStringItemSize = Marshal.SizeOf(); diff --git a/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs b/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs index 75d7920..be32901 100644 --- a/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs +++ b/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs @@ -94,16 +94,19 @@ namespace BMapSharp.BMapWrapper { #endregion } - public abstract class AbstractCKObject { - internal AbstractCKObject(IntPtr raw_pointer, uint ckid) { - m_RawPointer = raw_pointer; + public abstract class AbstractCKObject : SafeHandle { + // Same as AbstractPointer, but not own this handle. + internal AbstractCKObject(IntPtr raw_pointer, uint ckid) : base(Utils.INVALID_PTR, false) { + this.handle = raw_pointer; m_CKID = ckid; } - private readonly IntPtr m_RawPointer; + public override bool IsInvalid => this.handle == Utils.INVALID_PTR; + protected override bool ReleaseHandle() => throw new NotImplementedException(); + private readonly uint m_CKID; - protected bool isValid() => m_RawPointer != Utils.INVALID_PTR && m_RawPointer != Utils.INVALID_CKID; - protected IntPtr getPointer() => m_RawPointer; + protected bool isValid() => this.handle != Utils.INVALID_PTR && m_CKID != Utils.INVALID_CKID; + protected IntPtr getPointer() => this.handle; protected uint getCKID() => m_CKID; // private uint m_CKID; @@ -143,14 +146,14 @@ namespace BMapSharp.BMapWrapper { #region Misc - public override int GetHashCode() => HashCode.Combine(m_RawPointer, m_CKID); - public override string ToString() => $"{m_RawPointer}, {m_CKID}"; + public override int GetHashCode() => HashCode.Combine(this.handle, m_CKID); + public override string ToString() => $"{this.handle}, {m_CKID}"; #endregion } public class BMObject : AbstractCKObject { - internal BMObject(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) { } + internal BMObject(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { } public string GetName() { BMapException.ThrowIfFailed(BMap.BMObject_GetName( @@ -166,27 +169,27 @@ namespace BMapSharp.BMapWrapper { } public class BMTexture : BMObject { - internal BMTexture(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) { } + internal BMTexture(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { } } public class BMMaterial : BMObject { - internal BMMaterial(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) { } + internal BMMaterial(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { } } public class BMMesh : BMObject { - internal BMMesh(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) { } + internal BMMesh(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { } } public class BM3dObject : BMObject { - internal BM3dObject(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) { } + internal BM3dObject(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { } } public class BMGroup : BMObject { - internal BMGroup(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) { } + internal BMGroup(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { } } public sealed class BMFileReader : AbstractPointer { - private static IntPtr AllocateHandle(string file_name, string temp_folder, string texture_folder, string[] encodings) { + private static IntPtr allocateHandle(string file_name, string temp_folder, string texture_folder, string[] encodings) { BMapException.ThrowIfFailed(BMap.BMFile_Load( file_name, temp_folder, texture_folder, Utils.BMapSharpCallback, @@ -196,21 +199,20 @@ namespace BMapSharp.BMapWrapper { return out_file; } protected override bool ReleaseHandle() { - return BMap.BMFile_Free(this.handle); + return BMap.BMFile_Free(this.getPointer()); } public BMFileReader(string file_name, string temp_folder, string texture_folder, string[] encodings) - : base(AllocateHandle(file_name, temp_folder, texture_folder, encodings)) { } + : base(allocateHandle(file_name, temp_folder, texture_folder, encodings)) { } - - private delegate bool FctProtoGetCount(nint bmf, out uint cnt); - private delegate bool FctProtoGetObject(nint bmf, uint idx, out uint id); - private delegate T FctProtoCreateInstance(nint bmf, uint id); - private uint GetCKObjectCount(FctProtoGetCount fct_cnt) { + private delegate bool FctProtoGetCount(IntPtr bmf, out uint cnt); + private delegate bool FctProtoGetObject(IntPtr bmf, uint idx, out uint id); + private delegate T FctProtoCreateInstance(IntPtr bmf, uint id); + private uint getCKObjectCount(FctProtoGetCount fct_cnt) { BMapException.ThrowIfFailed(fct_cnt(this.getPointer(), out uint out_count)); return out_count; } - private IEnumerable GetCKObjects(FctProtoGetCount fct_cnt, FctProtoGetObject fct_obj, FctProtoCreateInstance fct_crt) { - uint count = GetCKObjectCount(fct_cnt); + private IEnumerable getCKObjects(FctProtoGetCount fct_cnt, FctProtoGetObject fct_obj, FctProtoCreateInstance fct_crt) { + uint count = getCKObjectCount(fct_cnt); for (uint i = 0; i < count; ++i) { BMapException.ThrowIfFailed(fct_obj(this.getPointer(), i, out uint out_id)); yield return fct_crt(this.getPointer(), out_id); @@ -218,26 +220,56 @@ namespace BMapSharp.BMapWrapper { } public uint GetTextureCount() => - GetCKObjectCount(BMap.BMFile_GetTextureCount); + getCKObjectCount(BMap.BMFile_GetTextureCount); public IEnumerable GetTextures() => - GetCKObjects(BMap.BMFile_GetTextureCount, BMap.BMFile_GetTexture, (bmf, id) => new BMTexture(bmf, id)); + getCKObjects(BMap.BMFile_GetTextureCount, BMap.BMFile_GetTexture, (bmf, id) => new BMTexture(bmf, id)); public uint GetMaterialCount() => - GetCKObjectCount(BMap.BMFile_GetMaterialCount); + getCKObjectCount(BMap.BMFile_GetMaterialCount); public IEnumerable GetMaterials() => - GetCKObjects(BMap.BMFile_GetMaterialCount, BMap.BMFile_GetMaterial, (bmf, id) => new BMMaterial(bmf, id)); + getCKObjects(BMap.BMFile_GetMaterialCount, BMap.BMFile_GetMaterial, (bmf, id) => new BMMaterial(bmf, id)); public uint GetMeshCount() => - GetCKObjectCount(BMap.BMFile_GetMeshCount); + getCKObjectCount(BMap.BMFile_GetMeshCount); public IEnumerable GetMeshes() => - GetCKObjects(BMap.BMFile_GetMeshCount, BMap.BMFile_GetMesh, (bmf, id) => new BMMesh(bmf, id)); + getCKObjects(BMap.BMFile_GetMeshCount, BMap.BMFile_GetMesh, (bmf, id) => new BMMesh(bmf, id)); public uint Get3dObjectCount() => - GetCKObjectCount(BMap.BMFile_Get3dObjectCount); + getCKObjectCount(BMap.BMFile_Get3dObjectCount); public IEnumerable Get3dObjects() => - GetCKObjects(BMap.BMFile_Get3dObjectCount, BMap.BMFile_Get3dObject, (bmf, id) => new BM3dObject(bmf, id)); + getCKObjects(BMap.BMFile_Get3dObjectCount, BMap.BMFile_Get3dObject, (bmf, id) => new BM3dObject(bmf, id)); public uint GetGroupCount() => - GetCKObjectCount(BMap.BMFile_GetGroupCount); + getCKObjectCount(BMap.BMFile_GetGroupCount); public IEnumerable GetGroups() => - GetCKObjects(BMap.BMFile_GetGroupCount, BMap.BMFile_GetGroup, (bmf, id) => new BMGroup(bmf, id)); + getCKObjects(BMap.BMFile_GetGroupCount, BMap.BMFile_GetGroup, (bmf, id) => new BMGroup(bmf, id)); } + public sealed class BMFileWriter : AbstractPointer { + private static IntPtr allocateHandle(string temp_folder, string texture_folder, string[] encodings) { + BMapException.ThrowIfFailed(BMap.BMFile_Create( + temp_folder, texture_folder, + Utils.BMapSharpCallback, + (uint)encodings.Length, encodings, + out IntPtr out_file + )); + return out_file; + } + protected override bool ReleaseHandle() { + return BMap.BMFile_Free(this.getPointer()); + } + public BMFileWriter(string temp_folder, string texture_folder, string[] encodings) + : base(allocateHandle(temp_folder, texture_folder, encodings)) { } + + private delegate bool FctProtoCreateObject(IntPtr bmf, out uint id); + private delegate T FctProtoCreateInstance(IntPtr bmf, uint id); + private T createCKObject(FctProtoCreateObject fct_crt, FctProtoCreateInstance fct_inst) { + BMapException.ThrowIfFailed(fct_crt(this.getPointer(), out uint out_id)); + return fct_inst(this.getPointer(), out_id); + } + + public BMTexture CreateTexture() => createCKObject(BMap.BMFile_CreateTexture, (bmf, id) => new BMTexture(bmf, id)); + public BMMaterial CreateMaterial() => createCKObject(BMap.BMFile_CreateMaterial, (bmf, id) => new BMMaterial(bmf, id)); + public BMMesh CreateMesh() => createCKObject(BMap.BMFile_CreateMesh, (bmf, id) => new BMMesh(bmf, id)); + public BM3dObject Create3dObject() => createCKObject(BMap.BMFile_Create3dObject, (bmf, id) => new BM3dObject(bmf, id)); + public BMGroup CreateGroup() => createCKObject(BMap.BMFile_CreateGroup, (bmf, id) => new BMGroup(bmf, id)); + } + }