英文:
Effectively convert bytes to array of structures in C#
问题
以下是翻译好的部分:
My C# application interacts with the C application via the "callbacks" mechanism.
On the C side I have Point
struct:
struct Point {
float x, y, z;
};
To transfer points from C to C# I pass my C# delegate callback function pointsCallback
to C function getPoints
.
typedef void(*PointsCallback)(const Point* points, int size);
void getPoints(PointsCallback callback);
delegate void PointsCallback(IntPtr points, int size);
[DllImport(...)]
static extern void getPoints(PointsCallback callback);
My PointsCallback
C# implementation looks like this:
[StructLayout(LayoutKind.Sequential)]
struct Point {
public float x, y, z;
}
// called from c code
void PointsCallbackImpl(IntPtr points, int size) {
var pointSize = Marshal.SizeOf<Point>();
var myPoints = new List<Point>();
for (int i = 0; i < size; ++i) {
myPoints.Add(Marshal.PtrToStructure<Point>(points + i * pointSize));
}
// do something with myPoints
}
The problem is this code is quite slow compared to python's np.array
which allows me to save all points
as a binary array and interpret them via np.dtype
.
Is there any C# analog to np.array
behavior, which allows to store everything in binary form and only interpret data as some structs?
英文:
My C# application interacts with the C application via the "callbacks" mechanism.
On the C side I have Point
struct:
struct Point {
float x, y, z;
};
To transfer points from C to C# I pass my C# delegate callback function pointsCallback
to C function getPoints
.
typedef void(*PointsCallback)(const Point* points, int size);
void getPoints(PointsCallback callback);
delegate void PointsCallback(IntPtr points, int size);
[DllImport(...)]
static extern void getPoints(PointsCallback callback);
My PointsCallback
C# implementation looks like this:
[StructLayout(LayoutKind.Sequential)]
struct Point {
public float x, y, z;
}
// called from c code
void PointsCallbackImpl(IntPtr points, int size) {
var pointSize = Marshal.SizeOf<Point>();
var myPoints = new List<Point>();
for (int i = 0; i < size; ++i) {
myPoints.Add(Marshal.PtrToStructure<Point>(points + i * pointSize));
}
// do something with myPoints
}
The problem is this code is quite slow compared to python's np.array
which allows me to save all points
as a binary array and interpret them via np.dtype
.
Is there any C# analog to np.array
behavior, which allows to store everything in binary form and only interpret data as some structs?
答案1
得分: 3
你可以使用 System.Memory<T>
类型来与包含二进制数据表示的内存块进行交互。它允许将数据解释为某个结构体。
示例:
struct Example
{
public int IntValue;
public float FloatValue;
}
byte[] dataBytes = new byte[] { 0x01, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00 };
Memory<byte> dataMemory = new Memory<byte>(dataBytes);
// 将内存强制转换为 Memory<Example> 对象
Memory<Example> dataMemory = MemoryMarshal.Cast<byte, Example>(dataMemory);
Example data = dataMemory.Span[0];
int intValue = data.IntValue; // intValue == 1
float floatValue = data.FloatValue; // floatValue == 1.0f
英文:
You can use System.Memory<T>
type to interact with a block of memory containing a binary data representation. It allows interpreting the data as some struct.
Example:
struct Example
{
public int IntValue;
public float FloatValue;
}
byte[] dataBytes = new byte[] { 0x01, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00 };
Memory<byte> dataMemory = new Memory<byte>(dataBytes);
// Cast the memory to a Memory<Example> object
Memory<MyData> dataMemory = MemoryMarshal.Cast<byte, Example>(dataMemory);
MyData data = dataMemory.Span[0];
int intValue = data.IntValue; // intValue == 1
float floatValue = data.FloatValue; // floatValue == 1.0f
答案2
得分: 3
以下是您要翻译的部分:
"不确定这个上下文中的 'slow' 是什么意思,但下面的示例需要0.3285毫秒,或328500纳秒来转换1000个点。"
"并且这是我的测试:"
英文:
I am not sure what 'slow' means in this context, but the example below takes 0.3285 milliseconds, or 328500 nanoseconds to convert 1000 points.
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static unsafe extern void memcpy(void* dst, void* src, int count);
[StructLayout(LayoutKind.Sequential)]
struct Point
{
public float x, y, z;
}
static unsafe void PointCallback(IntPtr ptPoints, int size)
{
Point[] points = new Point[size];
fixed (void* pDest = &points[0]) {
memcpy(pDest, (void*)ptPoints, Marshal.SizeOf<Point>() * size);
}
}
And here is my test:
Point[] points = new Point[1000];
for (int i=0; i<1000; i++) {
points[i] = new Point() { x= i, y = i,z = i };
}
var ptPoints = GCHandle.Alloc(points, GCHandleType.Pinned);
PointCallback(ptPoints.AddrOfPinnedObject(), 1000);
ptPoints.Free();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论