gpt4 book ai didi

Passing string as blittable type for UnmanagedCallersOnly native method(将字符串作为UnmanagedCallersOnly本机方法的blitable类型传递)

转载 作者:bug小助手 更新时间:2023-10-22 16:39:12 44 4
gpt4 key购买 nike



Trying to use the UnmanagedCallersOnly attribute but I'm stuck on some string fields in the structure. Is it possible to model this structure that is usable with the new UnmanagedCallersOnly attribute?

试图使用UnmanagedCallersOnly属性,但我被结构中的一些字符串字段卡住了。是否可以对可与新的UnmanagedCallersOnly属性一起使用的结构进行建模?


C++ structure:


struct PluginInfo {
int nStructSize;
int nType;
int nVersion;
char szName[ 64 ];
char szVendor[ 64 ];
};

I'm getting stuck on converting the szName and szVendor to c#.

我一直在把szName和szVendor转换成c#。


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct PluginInfo
{
public int StructSize;

[MarshalAs(UnmanagedType.I4)]
public PluginType Type; // PluginType is an enumeration

public int Version;

[MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)] //[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 64)]
public string Name;

[MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)] //[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 64)]
public string Vendor;
}


public class Plugin
{
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
public static void GetPluginInfo(ref PluginInfo pluginInfo)
{

pluginInfo.Name = "myPluginName";
pluginInfo.Vendor = "myVendorName";
pluginInfo.Type = PluginType.Data;
pluginInfo.StructSize = Marshal.SizeOf((PluginInfo)pluginInfo);

}
}

The error is "Cannot use 'PluginInfo' as a parameter type on a method attributed with 'UnmanagedCallersOnly'"

错误为“无法将'PluginInfo'用作具有'UnmanagedCallersOnly'属性的方法的参数类型”


更多回答

UnmanagedType.ByValTStr instead of LPWStr

UnmanagedType.ByValTStr而不是LPWStr

@Charlieface Unfortunately, that gives me the same error.

@Charlieface不幸的是,这给了我同样的错误。

You definitely need that anyway. char[] instead of string and ByValArray? I'm not sure UnmanagedCallersOnly is possible here at all

无论如何,你肯定需要它。char[]而不是字符串和ByValArray?我不确定UnmanagedCallersOnly在这里是否可行

Still doesn't work. I may have to assume that it's not supported.

仍然不起作用。我可能不得不假设它没有得到支持。

Needs to be blittable see this doc not sure why it's not working with a char array

需要可blitable查看此文档,不确定为什么它不能使用char数组

优秀答案推荐

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

unsafe struct PluginInfo
{
public int nStructSize;
public int nType;
public int nVersion;
// fixed means in place buffer, like in your C++ declaration
public fixed char szName[64];
public fixed char szVendor[64];
};

class d{
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
unsafe public static void GetPluginInfo(PluginInfo* info)
{
// PluginInfo required to be blittable, so we can use sizeof directly
Debug.Assert(Marshal.SizeOf<PluginInfo>() == sizeof(PluginInfo));
info->nStructSize = sizeof(PluginInfo);

// use Span
var s = new Span<char>(info->szName, 64);
"hello".CopyTo(s);
s["hello".Length] = '\0'; // it's `sz`, so null terminator is required

// or use pointer directly
info->szName[0] = 'x';
}

unsafe static void Main()
{
delegate* unmanaged[Cdecl]<PluginInfo*, void> callback = &GetPluginInfo;

PluginInfo inf = default; // zero initializedd, unless SkipLocalsInit applied
callback(&inf);

// copy to string
var name = new string(inf.szName/*, 0, 64 - 1*/);
// or use [ReadOnly]Span
var name2 = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(inf.szName);

Console.WriteLine(name);
Console.WriteLine(name2.SequenceEqual(name));
Console.WriteLine(name2.SequenceEqual("xello"));
Console.WriteLine(inf.nStructSize == (64 + 64) * sizeof(char) + sizeof(int) * 3);
}
}

更多回答

I've abandoned the project a while ago and will have to dig out the code to test it but I'll go ahead and accept it as the answer. Thanks.

我不久前放弃了这个项目,将不得不挖掘代码来测试它,但我会继续接受它作为答案。谢谢

@Ceres added some comments. You can play with it on sharplab.io

@Ceres补充了一些评论。你可以在sharplab.io上玩

44 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com