[英]How to call an ActiveX function with char * parameter in C#
我有这个c ++函数:
unsigned int ReadUserMemory( unsigned char *lpBuffer, unsigned int iAddress, unsigned int nNumberOfByte );
它从内存的iAddress
读取nNumberOfByte
字节并将其放入lpBuffer
。
我为此接口创建了一个ATL对象(将在C#中使用):
[id(6), helpstring("method ReadUserMemory")] HRESULT ReadUserMemory(BYTE* lpBuffer, [in] ULONG iAddress, [in] ULONG nNumberOfByte, [out,retval] ULONG* result);
我既不是C#程序员,也不是经验丰富的ATL程序员! 现在,我将使用以下代码在C#中测试此功能:
byte [] b = new byte[100];
axObj.ReadUserMemory(b, 0, 100);
但是显然,此代码是错误的。 如何调用此方法? 提前致谢。
我认为Peter R有一个非常有效的观点,因为使用COM很复杂,因为您需要学习COM以及C ++和C#。 C ++互操作是另一种选择,但是它还需要学习第三种技术,称为C ++ / CLI,它可能比COM更合适,但仍然会出现问题。 COM和C ++ / CLI都是很大的,复杂的野兽,因此您最好在dll中声明所需的C函数并使用P / Invoke,这可能会更好,请参见例如http://msdn.microsoft.com/zh-cn /magazine/cc164123.aspx 。 如果是这样,可以在如何使用C#中的p / invoke将指针传递给数组的方法中找到所需的魔术? 。
假设您想继续沿着COM路线前进,我一直在玩弄它,对我来说,您似乎需要通过嵌入在COM dll中的类型库来获得一些可以正常工作的东西。 简而言之,我无法使COM interop与unsigned char *lpBuffer
,尽管也许其他人可以! 类型库友好类型使用的是SAFEARRAY,这实际上是VB喜欢查看数组的方式。
在这种情况下,您的idl变为
[id(1)] HRESULT ReadUserMemory([out] SAFEARRAY(byte)* buffer, [in] ULONG iAddress, [in] ULONG nNumberOfByte, [out,retval] ULONG* result);
您的C ++实现看起来像这样
STDMETHODIMP CObj::ReadUserMemory(SAFEARRAY ** pBuffer, ULONG iAddress, ULONG nNumberOfByte, ULONG* result)
{
if (pBuffer== nullptr)
return E_POINTER;
SAFEARRAY*& psa = *pBuffer;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = nNumberOfByte;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
if(psa == NULL)
return E_OUTOFMEMORY;
void* data = nullptr;
SafeArrayAccessData(psa, &data);
for(int i=0; i<nNumberOfByte; ++i) {
((char*)data)[i] = (char)i;
}
SafeArrayUnaccessData(psa);
return S_OK;
}
该SafeArrayUnaccessData
应即使之后代码调用SafeArrayAccessData
失败。
C#客户端现在看起来像这样,特别是我们已经从byte[]
更改为System.Array
static void Main(string[] args)
{
RUMLib.IObj axObj = new RUMLib.Obj();
Array a = null;
axObj.ReadUserMemory(out a, 2, 6);
for (int i = 0; i < a.Length; ++i)
{
Console.Write("{0},", a.GetValue(i));
}
Console.WriteLine();
}
该程序的输出是
0,1,2,3,4,5,
请注意,由于数据从SAFEARRAY返回到C#数组,因此可能会进行编组,即复制数据。 这可能对您来说代价过高,在这种情况下,建议您使用C ++ / CLI或P / Invoke。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.