我正在try 创建C#代码,它调用带有C接口的DLL中的函数.我是一名C和C++专家,但我对C#的了解相当有限.我已经设法将DLL加载到C#程序中,并调用其接口使用简单数据类型(如int甚至字符串)的函数.但这个问题超出了我的能力范围,我希望能得到一些有用的提示.

DLL声明此入口点:

BOOL WINAPI GetUsers(ALLUSERINFO* pInfo, DWORD size, DWORD* count);

其中pInfo指向具有size个元素的C struct 数组,GetUsers函数用数据填充这些元素.count接收实际填充的数组元素的数量.pInfocount都是仅限出局的.

ALLUSERINFO的定义为

struct ALLUSERINFO : public USER_INFO2, public PRINCIPAL_INFO
{
    WCHAR Name[10];
    WCHAR Role[256];
};

它的基类是

struct USER_INFO2
{
    WCHAR Name[80];
    WCHAR Password[40];
};
struct PRINCIPAL_INFO
{
    int PrincipalStatus;
    WCHAR UniqueID[39];
};

(WCHARwchar_t的类型定义.)

我假设我必须将基类转换为ALLUSERINFO的嵌入成员,但我完全不知道如何在C#中创建包含固定大小C字符串的 struct 数组,然后通过指针将该数组传递给它的第一个元素.

我找到了StructLayoutMarshalAs属性,但从我阅读的文档中,我甚至不确定它们是否适合我的情况,更不用说当涉及到 struct 的 struct 数组时,更不用说它们如何工作了,就像本例中的情况一样.

谢谢!

推荐答案

最后,我找到了一个解决方案.它可能不是优雅的,但它是有效的.

我需要以下C#声明:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal unsafe struct USER_INFO2
{
    public fixed char Name[80];
    public fixed char Password[40];
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal unsafe struct PRINCIPAL_INFO
{
    internal int PrincipalStatus;
    public fixed char UniqueID[39];
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal unsafe struct ALLUSERINFO
{
    internal USER_INFO2 UserInfo;
    internal PRINCIPAL_INFO PrincipalInfo;
    public fixed char Name[10];
    public fixed char Role[256];
}

[DllImport("mydll.dll", CharSet = CharSet.Unicode)]
internal static extern bool GetUsers(ALLUSERINFO* pInfo, uint size, out uint count);

然后,对GetUsers的呼叫如下所示:

unsafe
{
    ALLUSERINFO[] buffer = new ALLUSERINFO[maxUsers];
    fixed (ALLUSERINFO* pBuffer = &buffer[0])
    {
        uint actualUsers;
        bool res = DSQL.DSEnumAllUsers(pBuffer, maxUsers, out actualUsers);
        if (!res)
            return false;
        // do something with the returned data in the buffer
    }
}

我不确定这struct个声明中是否所有属性都是必需的.关键的事情似乎是使用unsafefixed这两个关键词.

感谢@CharlieFace帮助我将我的 idea bootstrap 到正确的方向!

Csharp相关问答推荐

在Dapper中使用IasyncEum重写GetAsyncEum方法

什么是通过反射创建类的泛型接口方法的正确方法?

如何使用XmlSerializer反序列化字符串数组?

.NET 8 Web-API返回空列表

AsNoTrackingWithIdentitySolutions()似乎不起作用?

从Blob存储中提取tar.gz文件并将提取结果上载到另一个Blob存储

C#方法从AJAX调用接收NULL

JsonSerializer.Deserialize<;TValue>;(String,JsonSerializerOptions)何时返回空?

尽管保证密钥不同,但已添加相同密钥的项(&Q;)

try 在.Net核心身份注册页面中使用AJAX,但没有成功..NET Core 5.0 Razor页面应用程序

C#自定义验证属性未触发IsValid方法

如何返回具有泛型的类?

在集成测试中可以在模拟InMemory数据库中设定数据种子

在';、';附近有错误的语法.必须声明标量变量";@Checkin";.';

毛伊岛.NET 8图片不再适合按钮

在.NET Maui中,Flyoutindow/Hamburger菜单可以在shell 之外实现吗?

多个参数的最小API删除

Visual Studio如何使用当前的框架?

如何在单击按钮后多次异步更新标签

C#中COM对象的实际地址