我试图以这种方式分配一个结构数组:
struct T {
int a; int b;
}
data = Marshal.AllocHGlobal(count*Marshal.SizeOf(typeof(T));
...
Run Code Online (Sandbox Code Playgroud)
我想访问分配的数据"绑定"一个结构到分配给AllocHGlobal的数组中的每个元素...像这样的东西
T v;
v = (T)Marshal.PtrToStructure(data+1, typeof(T));
Run Code Online (Sandbox Code Playgroud)
但我没有找到任何方便的方法... 为什么IntPtr缺乏算术?我该如何以"安全"的方式解决这个问题?
有人可以确认PtrToStructure函数将数据复制到struct变量中吗?换句话说,修改结构体是否反映了结构数组数据中的修改?
当然,我想对使用struct的IntPtr指向的数据进行操作,而不是每次都复制数据,避免使用不安全的代码.
谢谢大家!
我有这段代码从扫描仪获取图像文件并将其保存在本地磁盘上:
IntPtr img = (IntPtr)pics[i];
SetStyle(ControlStyles.DoubleBuffer, false);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.Opaque, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.UserPaint, true);
bmprect = new Rectangle(0, 0, 0, 0);
bmpptr = GlobalLock(img);
pixptr = GetPixelInfo(bmpptr);
Gdip.SaveDIBAs(@"C:\", bmpptr, pixptr);
Run Code Online (Sandbox Code Playgroud)
问题出在这里Gdip.SaveDIBAs(@"C:\", bmpptr, pixptr);.保存对话框.

我想丢弃此对话框并将文件直接保存在我的驱动器中.
**Updated:**
public static bool SaveDIBAs(string picname, IntPtr bminfo, IntPtr pixdat)
{
SaveFileDialog sd = new SaveFileDialog();
sd.FileName = picname;
sd.Title = "Save bitmap as...";
sd.Filter =
"Bitmap file (*.bmp)|*.bmp|TIFF file (*.tif)|*.tif|JPEG file (*.jpg)|*.jpg|PNG file (*.png)|*.png|GIF file (*.gif)|*.gif|All files (*.*)|*.*";
sd.FilterIndex = 1;
return …Run Code Online (Sandbox Code Playgroud) 我想在非托管库中调用此方法:
void __stdcall GetConstraints(
unsigned int* puiMaxWidth,
unsigned int* puiMaxHeight,
unsigned int* puiMaxBoxes
);
Run Code Online (Sandbox Code Playgroud)
我的解决方案
代表定义:
[UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void GetConstraintsDel(UIntPtr puiMaxWidth,UIntPtr puiMaxHeight,UIntPtr puiMaxBoxes);
方法的调用:
// PLUGIN NAME
GetConstraintsDel getConstraints = (GetConstraintsDel)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(GetConstraintsDel));
uint maxWidth, maxHeight, maxBoxes;
unsafe
{
UIntPtr a = new UIntPtr(&maxWidth);
UIntPtr b = new UIntPtr(&maxHeight);
UIntPtr c = new UIntPtr(&maxBoxes);
getConstraints(a, b, c);
}
Run Code Online (Sandbox Code Playgroud)它有效,但我必须允许"不安全"的标志.有没有不安全代码的解决方案?或者这个解决方案好吗?我不太明白用不安全标志设置项目的含义.
感谢帮助!
我试图读取IntPtr引用到byte []然后再返回另一个IntPtr的数据.指针正在引用从扫描仪设备捕获的图像,因此我还假设捕获此信息应放入字节数组中.
我也不确定Marshal.SizeOf()方法是否会返回IntPtr引用的数据大小或指针本身的大小.
我的问题是我收到错误"类型'System.Byte []'不能被编组为非托管结构;没有有意义的大小或偏移量可以计算"
IntPtr bmpptr = Twain.GlobalLock (hImage);
try
{
byte[] _imageTemp = new byte[Marshal.SizeOf(bmpptr)];
Marshal.Copy(bmpptr, _imageTemp, 0, Marshal.SizeOf(bmpptr));
IntPtr unmanagedPointer = Marshal.AllocHGlobal(
Marshal.SizeOf(_imageTemp));
try
{
Marshal.Copy(_imageTemp, 0, unmanagedPointer,
Marshal.SizeOf(_imageTemp));
Gdip.SaveDIBAs(
string.Format("{0}\\{1}.{2}", CaptureFolder, "Test", "jpg"),
unmanagedPointer, false);
}
finally
{
Marshal.FreeHGlobal(unmanagedPointer);
}
}
catch (Exception e)
{
Scanner.control.Test = e.Message;
}
Run Code Online (Sandbox Code Playgroud) 这是一个看起来很简单的问题:
鉴于本地大小的整数是最好的算法,为什么不C#(或任何其他.NET语言)支持算术与本地大小IntPtr和UIntPtr?
理想情况下,您可以编写如下代码:
for (IntPtr i = 1; i < arr.Length; i += 2) //arr.Length should also return IntPtr
{
arr[i - 1] += arr[i]; //something random like this
}
Run Code Online (Sandbox Code Playgroud)
这样它就可以在32位和64位平台上运行.(目前,您必须使用long.)
编辑:
我没有使用它们作为指针(甚至没有提到"指针"这个词)!它们可以被视为native intMSIL和intptr_tC中的C#对应物stdint.h- 它们是整数,而不是指针.
我刚刚学会了IntPtr.Zero无法与默认(IntPtr)进行比较的困难方法.有人可以告诉我为什么吗?
IntPtr.Zero == new IntPtr(0) -> "could not evaluate expression"
IntPtr.Zero == default(IntPtr) --> "could not evaluate expression"
IntPtr.Zero == (IntPtr)0 -> "could not evaluate expression"
IntPtr.Zero.Equals(IntPtr.Zero) --> "Enum value was out of legal range" exception
IntPtr.Zero.Equals(default(IntPtr)) --> "Enum value was out of legal range" exception
IntPtr.Zero == IntPtr.Zero --> true
new IntPtr(0) == new IntPtr(0) --> true
Run Code Online (Sandbox Code Playgroud) 我无法弄清楚该Copy(IntPtr[], Int32, IntPtr, Int32)方法是如何工作的。我虽然它可以将包含在多个 IntPtr 中的数据复制到单个 IntPtr(如 MSDN 所述)但显然它不像我预期的那样工作:
IntPtr[] ptrArray = new IntPtr[]
{
Marshal.AllocHGlobal(1),
Marshal.AllocHGlobal(2)
};
Marshal.WriteByte(ptrArray[0], 0, 0xC1);
// Allocate the total size.
IntPtr ptr = Marshal.AllocHGlobal(3);
Marshal.Copy(ptrArray, 0, ptr, ptrArray.Length);
// I expect to read 0xC1 but Value is always random!!
byte value = Marshal.ReadByte(ptr, 0);
Run Code Online (Sandbox Code Playgroud)
有人知道我是否将这种方法用于不是它的目的吗?
这是我的原型:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool PostMessage(int hhwnd, uint msg, IntPtr wparam, IntPtr lparam);
Run Code Online (Sandbox Code Playgroud)
这是我如何使用它:
PostMessage(HWND_BROADCAST, msg, Marshal.StringToHGlobalAuto("bob"), IntPtr.Zero);
Run Code Online (Sandbox Code Playgroud)
在另一个线程中,我可以截获此消息,但是当我尝试使用以下方法取回 bob 时:
string str = Marshal.PtrToStringAuto(m.WParam); // where m = the Message object
Run Code Online (Sandbox Code Playgroud)
我没有得到鲍勃在 str。
我认为这一定是因为我在一个线程的堆栈上引用了“bob”字符串,而该引用在另一个线程的堆栈中绝对没有意义。但如果是这样的话,这些 wparam 和 lparam 指针真的只用于在同一线程中传递的消息吗?
编辑*更正:通过线程我的意思是进程。这是在进程之间传递字符串而不是线程的问题。
我有一个采用IntPtr的外部库。有没有安全的方法可以做到这一点...
int BytesWritten = 0;
Output.WriteBytes(buffer, new IntPtr(&BytesWritten));
Run Code Online (Sandbox Code Playgroud)
...而不必使用“不安全”代码?我对IntPtrs不太熟悉,但是我想做这样的事情:
fixed int BytesWritten = 0;
Output.WriteBytes(buffer, IntPtr.GetSafeIntPtr(ref BytesWritten));
Run Code Online (Sandbox Code Playgroud)
...以这种方式,我不需要使用/ unsafe进行编译。
我不能更改WriteBytes函数,它是一个外部函数。
似乎在'ref int'和IntPtr之间应该进行某种类型的转换,但是我还没有找到它的运气。
我在 C# 中有一个从 .dll 调用的方法
[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int find([MarshalAs(UnmanagedType.AnsiBStr, SizeConst = 64)] string atr, out IntPtr int);
[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int getData(IntPtr int, int dataId, byte[] dataBuffer, ref int dataBufferSize);
Run Code Online (Sandbox Code Playgroud)
在 C# 中调用这个方法看起来像这样
static IntPtr number = IntPtr.Zero;
static int res = 0;
try{
number = IntPtr.Zero;
res = find(null, out number);
if (number == IntPtr.Zero)
throw new ApplicationException("Something is wrong");
uint dataBufferSize = 1024;
res = getData(number, 1, null, ref …Run Code Online (Sandbox Code Playgroud) intptr ×10
c# ×8
.net ×4
marshalling ×4
arrays ×1
copy ×1
default ×1
image ×1
interop ×1
java ×1
jna ×1
parameters ×1
pointers ×1
postmessage ×1
save-dialog ×1
scanning ×1