0

我有现有的带有签名的 C# 代码Foo(long[][] longs),我需要从非托管 C++而不是C++/CLI)调用这些代码。我似乎无法找出正确的组合__gc[]__gc*让编译器满意。

使用 C++/CLI,这很简单:

std::vector<__int64> evens;
evens.push_back(2); evens.push_back(4); evens.push_back(6); evens.push_back(8);
std::vector<__int64> odds;
odds.push_back(1); odds.push_back(3); odds.push_back(5); odds.push_back(7);
std::vector<std::vector<__int64> > ints;
ints.push_back(evens); ints.push_back(odds);

array<array<__int64>^>^ mgdInts = gcnew array<array<__int64>^>(ints.size());
for (size_t i = 0; i<ints.size(); ++i)
{
    const std::vector<__int64>& slice = ints[i];
    mgdInts[i] = gcnew array<__int64>(slice.size());
    for (size_t j=0; j<slice.size(); ++j)
        mgdInts[i][j] = slice[j];
}

编辑:当我使用 Visual Studio 2008 时,“简单”的解决方案是将 C++/CLI 代码放在自己的文件中并使用/clr编译;当然,如果我不必这样做会更容易(例如,使用托管 C++ 的其他.h文件)。C# 代码无法更改,因为它是从 Web 参考自动生成的。

4

2 回答 2

1

将签名从这里更改为 Foo(long[][] longs)Foo(Array longs)

然后,当您查看 OleView.exe 中生成的类型库时,您应该看到:

    HRESULT Foo([in] SAFEARRAY(int64) longs);

从 C++ 开始,调用起来相当简单。你可以只用 Win32 创建一个 SAFEARRAY,或者我建议包含然后在 ATL 中使用 CComSafeArray 包装类。

尽管 C# 和 C++ 都具有更丰富的数组定义,但两者之间的互操作性通常是通过类型库编组器完成的,其中 99% 是遗留的并且基于“VB 兼容”。类型库编组器支持的唯一数组类型是 SAFEARRAY,因此当您按照正常方式执行所有这些操作时,您会得到它。

但是,COM 支持更丰富的数组系统(一致性数组),C# 可以理解,但更难做到,而且您不能简单地重新加载 C# DLL 并在非托管 C++ 程序中使用生成的类型库。一些技术需要使用 ILDASM 调整 C# 代码。其他人则要求您保留接口的两个定义,一个在 C++ 中,一个在 C# 中,并确保它们同步(无法将一个转换为另一个),然后在 C++ 的 IDL 中使用 size_is 装饰参数,在 C# 中使用 MarshalAs。这有点乱,实际上人们这样做的唯一类型是如果他们已经发布了他们无法更改的遗留界面。如果这是您的 C# 代码,并且您可以定义接口,我不会去那里。尽管如此,该技术仍然可用。这是一个参考:http://support. 如果您以前从未做过类似的事情,预计大约一周左右可以完成此任务。

于 2009-10-16T20:44:17.027 回答
0

我想出的解决方案是使用List<>.ToArray()

System::Collections::Generic::List<__int64 __gc[]>* mgdInts = new System::Collections::Generic::List<__int64 __gc[]>(ints.size());
for (size_t i = 0; i<ints.size(); ++i)
{
    const std::vector<__int64>& slice = ints[i];
    __int64 mgdSlice __gc[] = new __int64 __gc[slice.size()];
    for (size_t j=0; j<slice.size(); ++j)
        mgdSlice[j] = slice[j];

    mgdInts->Add(mgdSlice);
}

ClassLibrary1::Class1::Foo(mgdInts->ToArray());
于 2009-10-17T15:18:39.760 回答