C#学习教程:使用com可调用包装器将结构数组从c#传递到C++//为账户服务定义一个接口[ComVisible(true)][Guid("39B8A693-79BB-4638-92DE-245A88720953")]publicinterfaceIAccountStructLookup{AccountStructRetrieveAccount(intacctId);voidUpdateBalance(refAccountStruct帐户);别名[]GetRef();}//实现一个账户struct[ComVisible(true)][Guid("DB48C5B6-9646-491A-B030-C0CADCFC03E0")]publicstructAccountStruct{publicintAccountId;[MarshalAs(UnmanagedType.BStr)]publicstringAccountName;[MarshalAs(UnmanagedType.Currency)]publicdecimalBalance;//[MarshalAs(UnmanagedType.ByValArray,SizeConst=5)]//[MarshalAs(UnmanagedType.SafeArray)]//publicAlias[]别名;}[ComVisible(true)][Guid("9829CAB3-4020-47EA-BE72-86EC7CFFAE1D")]publicstructAlias{publicstringName;}//实现一个类来提供账户服务//使用AccountStruct[ComVisible(true)][Guid("CEFE5CAA-5C7E-464F-8020-E0FC78180D9B")][ClassInterface(ClassInterfaceType.None)]publicclassDniNetStructsObj:IAccountStructLookup{publicAccountStructRetrieveAccount(intacctId){AccountStruct结果=newAccountStruct();如果(acctId==123){结果.AccountId=acctId;result.AccountName="我的账户";结果.Balance=1009.95M;//result.Aliases=newAlias[5];//result.Aliases[0].Name="1";//result.Aliases[1].Name="2";//result.Aliases[2].Name="3";//result.Aliases[3].Name="4";//result.Aliases[4].Name="5";}返回结果;}publicvoidUpdateBalance(refAccountStructaccount){//更新余额account.Balance+=500.00M;}publicAlias[]GetRef(){Alias[]al=newAlias[2];al[0].Name="1";al[1].Name="2";返回al;}}而C++方面的东西#include"stdafx.h"#include"ConsoleApplication1.h"#import"D:SourceCodeMarshalLibMarshalLibbinDebugMarshalLib.tlb"raw_interface_only#ifdef_DEBUG#definenewDEBUG_NEW#endif//唯一的应用程序对象CWinApptheApp;使用命名空间标准;使用命名空间MarshalLib;int_tmain(intargc,TCHAR*argv[],TCHAR*envp[]){intnRetCode=0;HMODULEhModule=::GetModuleHandle(NULL);if(hModule!=NULL){//初始化MFC并在失败时打印和错误if(!AfxWinInit(hModule,NULL,::GetCommandLine(),0)){//TODO:更改错误代码以满足您的需要_tprintf(_T("致命错误:MFC初始化失败n"));nRetCode=1;}else{尝试{CoInitialize(NULL);IAccountStructLookupPtrapi(__uuidof(DniNetStructsObj));api->GetRef();CoUninitialize();}catch(...){}}}else{//TODO:更改错误代码以满足您的需要_tprintf(_T("FatalError:GetModuleHandlefailedn"));nRetCode=1;}返回nRetCode;当我调用api-GetRef()获取结构数组时出现错误时请帮助我从c#返回一个结构数组并在c++中使用它。提前致谢。返回数组的问题在于,在C++中,您会看到一个指向结构的指针,但看不到有关数组大小的信息。您可以尝试将其组织为SAFEARRAY,但在我看来,SAFEARRAY很麻烦。我更喜欢将其建模为:[ComVisible(true)][Guid("C3E38106-F303-46d9-9EFB-AD8A8CA8644E")][StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]publicstructMyStruct{publicintValue;//我将字符串编组为数组!请参阅底部的注释[MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)]publicstringUnit}[ComVisible(true),Guid("BD4E6810-8E8C-460c-B771-E266B6F9122F"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]public接口IMyService{intGetData([MarshalAs(UnmanagedType.LPArray)]outMyStruct[]数据);}客户端代码是这样的:Lib::MyStruct*data;长尺寸=svc->GetData(&data);for(size_ti=0;i对SAFEARRAY的评论:仅当接口必须符合自动化时才需要它们,即后期绑定,即IDispatch接口,即标记为ComInterfaceType.InterfaceIsIDispatch。如果不是这样,在这种情况下(我将接口声明为自定义,即ComInterfaceType.InterfaceIsIUnknown)使用标准数组非常好,它们与SAFEARRAY一样得到很好的支持。此外,为SAFEARRAY使用自定义结构会引入一些额外的复杂性,我希望避免这种情况。如果你不需要后期具有约束力,没有理由对抗SAFEARRAY。关于CComSafeArray,正如文档所说,它不支持支持结构数组所需的VT_RECORD(另一种选择是将其作为带有IRecordInfo的VT_VARIANT,但我什至不会深入探讨)。您首先需要通过接口公开托管代码并使用regasm注册它并创建类型库(tlb文件)。然后您可以在非托管代码中使用它。看这篇文章:http://blogs.msdn.com/b/deeptanshuv/archive/2005/06/26/432870.aspx以上是C#学习教程:Passinganarrayofstructsfromc#usingacomcallablewrapper所有针对C++分享的内容,如果对你有用,需要了解更多C#学习教程,希望大家多多关注---本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
