আমি byte[]কোনও পদ্ধতিতে পাস করতে চাই IntPtr# # তে একটি প্যারামিটার লাগে , এটি কি সম্ভব এবং কীভাবে?
GCHandleপদ্ধতিটি কবজির মতো কাজ করে ... fixedপদ্ধতিটিও। : পি :))
আমি byte[]কোনও পদ্ধতিতে পাস করতে চাই IntPtr# # তে একটি প্যারামিটার লাগে , এটি কি সম্ভব এবং কীভাবে?
GCHandleপদ্ধতিটি কবজির মতো কাজ করে ... fixedপদ্ধতিটিও। : পি :))
উত্তর:
কোনও অ্যারেতে একটি ইন্টারপ্রিটি পাওয়ার বিষয়ে নিশ্চিত নন, তবে আপনি মশাল.কপি ব্যবহার করে নিয়ন্ত্রণহীন কোড সহ ডেটা অনুলিপি করতে পারেন:
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);
বিকল্পভাবে আপনি একটি সম্পত্তি সহ একটি স্ট্রাক্ট ঘোষণা করতে পারেন এবং তারপরে মার্শাল.প্রিটারটোস্ট্রাক্ট ব্যবহার করতে পারেন, তবে তার জন্য এখনও পরিচালনা না করা মেমরির বরাদ্দ প্রয়োজন।
সম্পাদনা: এছাড়াও, যেমন Tyalis নির্দিষ্ট, এছাড়াও আপনি ব্যবহার করতে পারেন নির্দিষ্ট যদি অনিরাপদ আপনি যে কোডটি জন্য একটি বিকল্প
Marshal.Copyসেই ওভারলোডের সাথে একটি সূচনা সূচক প্রয়োজন। কলটি হওয়া উচিতMarshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
অন্য উপায়,
GCHandle pinnedArray = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
// Do your stuff...
pinnedArray.Free();
এটি কাজ করা উচিত তবে এটি অনিরাপদ প্রসঙ্গে ব্যবহার করা উচিত:
byte[] buffer = new byte[255];
fixed (byte* p = buffer)
{
IntPtr ptr = (IntPtr)p;
// do you stuff here
}
সাবধান, আপনি নির্দিষ্ট ব্লকে পয়েন্টার ব্যবহার করতে হবে! আপনি আর স্থির ব্লকের মধ্যে না থাকলে একবার গিসি অবজেক্টটি সরাতে পারে।
আপনি Marshal.UnsafeAddrOfPinnedArrayElement(array, 0)অ্যারেতে একটি মেমরি পয়েন্টার পেতে ব্যবহার করতে পারেন ।
এখানে @ ব্যবহারকারী 65157 এর উত্তরে একটি টুইস্ট রয়েছে (তার জন্য +1, বিটিডাব্লু):
আমি পিনযুক্ত অবজেক্টের জন্য একটি আইডিস্পোজযোগ্য মোড়ক তৈরি করেছি:
class AutoPinner : IDisposable
{
GCHandle _pinnedArray;
public AutoPinner(Object obj)
{
_pinnedArray = GCHandle.Alloc(obj, GCHandleType.Pinned);
}
public static implicit operator IntPtr(AutoPinner ap)
{
return ap._pinnedArray.AddrOfPinnedObject();
}
public void Dispose()
{
_pinnedArray.Free();
}
}
তারপরে এটিকে এভাবে ব্যবহার করুন:
using (AutoPinner ap = new AutoPinner(MyManagedObject))
{
UnmanagedIntPtr = ap; // Use the operator to retrieve the IntPtr
//do your stuff
}
আমি ফ্রি () :) এ কল করতে ভুলে যাবেন না এটি একটি দুর্দান্ত উপায় বলে মনে হয়েছে
মার্শাল.কপি কাজ করে তবে ধীর হয়। দ্রুত লুপের জন্য বাইটস অনুলিপি করা হয়। আরও দ্রুত হ'ল বাইট অ্যারেটি একটি অতি দীর্ঘ অ্যারেতে কাস্ট করা, বাইট অ্যারে অনুসারে যতটা উলং কপি করা হয়, তারপরে সম্ভাব্য অবশিষ্ট 7 বাইট (8 টি বাইট সারিবদ্ধ নয় এমন ট্রেইল) অনুলিপি করুন। দ্রুততমটি হল টায়ালিসের উত্তরে প্রস্তাবিত হিসাবে একটি নির্দিষ্ট বিবৃতিতে বাইট অ্যারে পিন করা।
IntPtr GetIntPtr(Byte[] byteBuf)
{
IntPtr ptr = Marshal.AllocHGlobal(byteBuf.Length);
for (int i = 0; i < byteBuf.Length; i++)
{
Marshal.WriteByte(ptr, i, byteBuf[i]);
}
return ptr;
}
কিছু ক্ষেত্রে আপনি ইন্টিপিটিআর ক্ষেত্রে একটি ইন্টার 32 টাইপ (বা ইন্টার 64) ব্যবহার করতে পারেন। আপনি যদি পারেন তবে অন্য দরকারী শ্রেণি হ'ল বিটকনভার্টার। আপনি যা চান তার জন্য আপনি বিটকনভার্টার ব্যবহার করতে পারেন o টুআইন্ট 32 উদাহরণস্বরূপ।
Int32একটি পয়েন্টার হিসাবে ব্যবহার করতে পারেন । এটি বহু বছর আগে করা একটি খারাপ অভ্যাস ছিল এবং এটি সমস্ত ধরণের পোর্টিংয়ের সমস্যার দিকে পরিচালিত করে। এমনকি একটি Int64নিরাপদ নয় কারণ ইতিমধ্যে 128-বিট আর্কিটেকচার রয়েছে এবং পয়েন্টারের আকার বৃদ্ধি পাবে। পয়েন্টারগুলিকে কেবল পয়েন্টার হিসাবে প্রতিনিধিত্ব করা উচিত।
int/ ব্যবহারের জন্য একমাত্র বৈধ longদৃশ্যাবলীটি যখন ব্যবহৃত ভাষার কোনও ধারণা না থাকে (উদাহরণস্বরূপ ভিবি 6)। সি # পয়েন্টারগুলিকে সমর্থন করে এবং রয়েছে IntPtr- intকখনও কোনও পয়েন্টারের জায়গায় কোনও ব্যবহার করার দরকার নেই । যদি আপনি আপনার উত্তরে স্পষ্ট সতর্কতা এবং সম্ভাব্য সমস্যার ব্যাখ্যা যোগ করেন তবে আমি আমার -1 সরিয়ে ফেলব।