gpt4 book ai didi

c# - 函数的 IDL 声明(在 C++ 中)将从 C# 获取 C 样式数组

转载 作者:行者123 更新时间:2023-11-28 08:34:20 25 4
gpt4 key购买 nike

我正在使用一个现有代码库,该代码库由一些用 C++ 编写的带有 C# 前端的 COM 接口(interface)组成。有一些新功能需要添加,所以我不得不修改 COM 部分。在一种特殊情况下,我需要将一个数组(从 C# 分配)传递给要填充的组件。

我想做的是能够将一个 int 数组传递给 C# 中的方法,例如:

// desired C# signature
void GetFoo(int bufferSize, int[] buffer);

// desired usage
int[] blah = ...;
GetFoo(blah.Length, blah);

工作中的几个 Spanner :

  • 不能使用 C++/CLI 或托管 C++(在这种情况下可以取消 COM)。
  • C# 端不能用/unsafe 编译(允许使用 Marshal)。

COM 接口(interface)仅由 C# 部分使用(并且永远只会使用),因此我不太关心与其他 COM 使用者的互操作性。 32 位和 64 位之间的可移植性也不是问题(一切都在 32 位机器上编译和运行,因此代码生成器将指针转换为整数)。最终,它将仅被 C++/CLI 取代,但这还有很长的路要走。


我的初步尝试

类似于:

HRESULT GetFoo([in] int bufferSize, [in, size_is(bufferSize)] int buffer[]);

并且输出的TLB定义是(貌似合理):

HRESULT _stdcall GetFoo([in] int bufferSize, [in] int* buffer);

这是由 C# 导入的(不太合理):

void GetFoo(int bufferSize, ref int buffer);

可以使用

int[] b = ...;
fixed(int *bp = &b[0])
{
GetFoo(b.Length, ref *bp);
}

...除了我无法使用/unsafe 进行编译。


此刻

我正在使用:

HRESULT GetFoo([in] int bufferSize, [in] INT_PTR buffer);

导入为:

void GetFoo(int bufferSize, int buffer);

我需要像这样使用它:

int[] b = ...;
GCHandle bPin = GCHandle.Alloc(b, GCHandleType.Pinned);
try
{
GetFoo(b.Length, (int)Marshal.UnsafeAddrOfPinnedArrayElement(b, 0));
}
finally
{
bPin.Free();
}

哪个有效...,但我想找到一种更简洁的方法。


所以,问题是

在这种情况下,是否有对从 TLB 生成器导入 C# 友好的 IDL 定义?如果不是,在 C# 端可以做些什么来让它更安全一些?

最佳答案

因此,您要求 IDL 数据类型在 32 位机器上为 32 位,在 64 位机器上为 64 位。但是您不希望编码(marshal)处理代码将其视为指针,只是作为 int。那么,当您从 64 位进程调用 32 位进程时,您希望额外的 32 位发生什么情况?

对我来说这听起来像是违反物理学的。

如果它只是 inproc,请参阅此讨论的底部:http://www.techtalkz.com/vc-net/125190-how-interop-net-client-com-dll.html .

建议似乎是使用 void * 而不是 intptr 并用 [local] 标记,这样编码器就不会参与。

关于c# - 函数的 IDL 声明(在 C++ 中)将从 C# 获取 C 样式数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/199629/

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