我正在尝试使用C#编写的库的C ++。为此,我被告知要使用COM Interop,我对此知之甚少。 我试图以一种方式传递一维数组并返回一维数组,但我的返回数组最终只是满了零。 为了简化这个论坛的问题,我简化了我的程序:我甚至没有传递输入数组。
我的C#程序看起来像这样
using System;
using System.Runtime.InteropServices;
namespace FillArray
{
[ComVisible(true)]
[Guid("DABAEF7C-D2B8-4769-98C8-1AF211EF7D48")]
public interface IFillArray
{
int fillTheArrayWithSquares(int[] array);
}
[ComVisible(true)]
[Guid("124A66FD-CED3-4a8e-B0F0-BAA88B421E97")]
public class Class1: IFillArray
{
public int fillTheArrayWithSquares(int[] array)
{
int len = array.Length;
int i;
for (i = 0; i < len; i++)
array[i] = i * i;
return len;
}
}
}
在同一解决方案中,我有一个C ++客户端,如下所示:
#import "D:\dev\CSharp\FillArray\FillArray\bin\Release\FillArray.tlb" raw_interfaces_only
#include "stdafx.h"
using namespace FillArray;
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = CoInitialize(NULL);
long retval;
IFillArrayPtr pIFillArray(__uuidof(Class1));
SAFEARRAY *output;
SAFEARRAYBOUND BoundOutput;
BoundOutput.cElements = 10;
BoundOutput.lLbound = 0;
output = SafeArrayCreate(VT_I4, 1, &BoundOutput);
int *p_output_contents;
HRESULT hrFill = pIFillArray->fillTheArrayWithSquares( output, &retval);
HRESULT hrOutput = SafeArrayAccessData(output, (void HUGEP**)&p_output_contents);
if(SUCCEEDED(hrFill) && SUCCEEDED(hrOutput))
{
for(int i = 0; i < 10; i++)
printf("%d ",p_output_contents[i]);
printf("\n");
printf("retval = %d\n",retval);
SafeArrayUnaccessData(output);// not robust error handling
SafeArrayDestroy(output);//not robust error handling logic
}
CoUninitialize();
return 0;
}
我已经将C ++项目配置为使用/ clr:oldsyntax,因为我正在修改一篇推荐它的旧文章。不幸的是,在VS 2008(我正在使用)中看起来这已被弃用了,我将无法将其移植到VS2013。 所以我有两个问题: 1)为什么我的C ++应用程序打印10个零? 2)如何更新我的语法以避免/ clr:oldsyntax。
还有一句话:我在一些讨论中看到C#数组与SAFEARRAYS不对应,但类型的选择是Intellisense告诉我应该使用的。 THX。
答案 0 :(得分:2)
首先,VS中有两种类型的C ++项目:
如果本机C ++项目想要使用C#DLL,一种方法是通过COM,另一种方法是使用C ++ CLI项目作为桥梁。
如果你使用COM,那么你必须处理容易出错的SAFEARRAY。至于你的问题1,你使用SAFEARRAY作为out参数,这很复杂。我建议你只需将函数fillTheArrayWithSquares的定义更改为:
public int[] fillTheArrayWithSquares( )
因此它将返回SAFEARRAY到C ++代码,SAFEARRAY的长度已包含在SAFEARRAY中。