将应用程序从 VB 重写为 C++ 并得到错误 0070
Posted
技术标签:
【中文标题】将应用程序从 VB 重写为 C++ 并得到错误 0070【英文标题】:Rewrite application from VB to C++ and get error 0070 【发布时间】:2021-12-15 23:07:52 【问题描述】:我正在将 COM 的客户端应用程序从 VB 重写为 C++:
VB
Private Sub Command1_Click()
Dim proxy As Person
Set proxy = New Person
proxy.FirstName = "Maxim"
proxy.LastName = "Donax"
proxy.Persist ("C:\myFile.xml")
End Sub
C++
#import "COM.tlb" raw_interfaces_only, raw_native_types, no_namespace, named_guids
#include <iostream>
int main()
Person per; // error 0070
per.FirstName = "Maxim"; // error 3365
per.LastName = "Donax";// error 3365
per.Persist(" C:\myFile.xml ");// error 3365
我得到一个错误 E0070:Incomplete type not allowed, 它本身会产生错误 3365: Incomplete type not allowed of class "Person" in next strings
我明白我做错了什么,但我找不到正确的解决方案。请帮忙。
COM.tlb:
using System.Xml.Serialization;
using System.IO;
using System.Runtime.InteropServices;
namespace COM
[ClassInterface(ClassInterfaceType.None)]
public class Person : System.EnterpriseServices.ServicedComponent, IPerson
public string FirstName get; set;
public string LastName get; set;
public bool IsMale get; set;
public void Persist(string FilePath)
StreamWriter oFile = new StreamWriter(FilePath);
XmlSerializer oXmlSerializer = new XmlSerializer(typeof(Person));
oXmlSerializer.Serialize(oFile, this);
oFile.Flush();
oFile.Close();
static public Person Retrieve(string FilePath)
StreamReader oFile = new StreamReader(FilePath);
XmlSerializer oXmlSerilizer = new XmlSerializer(typeof(Person));
Person oPerson = oXmlSerilizer.Deserialize(oFile) as Person;
return oPerson;
IPerson.cs
using System;
namespace COM
public interface IPerson
string FirstName get; set;
bool IsMale get; set;
string LastName get; set;
void Persist(string FilePath);
【问题讨论】:
IPerson在C#中是如何定义的? @SimonMourier 添加了 IPerson.cs,你想看看,对吧? 在 C++ 中,您不声明Person
的实例,而是声明指向它的指针。 #import
将为 _com_ptr_t
智能指针创建一堆方便的 typedef。你应该声明类似PersonPtr
的东西。我不记得创建一个新的Person
对象的仪式,但是你可能会找到一个_com_ptr_t
的成员来为你做这件事。因为它是一个指针(或类似指针的对象),您将使用->
而不是.
访问成员。
【参考方案1】:
您必须学习一点 C++ 才能做到这一点。
还可以看看 Visual Studio 在输出文件夹中生成的 .tlh
(可能还有 .tli
)文件。
所以,这里是如何实例化和调用 COM 对象(例如使用来自 comdef.h 的 Windows SDK 工具/包装器,如 _bstr_t
):
#include <windows.h>
#import "COM.tlb" raw_interfaces_only, raw_native_types, no_namespace, named_guids
int main()
CoInitialize(NULL);
IPersonPtr per(__uuidof(Person)); // equivalent of CoCreateInstance(CLSID_Person,..., IID_IPerson, &person)
per->put_FirstName(_bstr_t(L"Maxim"));
per->put_LastName(_bstr_t(L"Donax"));
per->Persist(_bstr_t(L"c:\\myFile.xml"));
CoUninitialize();
return 0;
或者更简单一点(使用自动生成的便捷包装器):
#include <windows.h>
#import "COM.tlb"
using namespace COM; // your namespace, COM is probably not a good namespace name
int main()
CoInitialize(NULL);
IPersonPtr per(__uuidof(Person));
per->PutFirstName(L"Maxim");
per->PutLastName(L"Donax");
per->Persist(L"c:\\myFile.xml");
CoUninitialize();
return 0;
【讨论】:
我对C++一无所知;只是好奇。我发现指针变量IPersonPtr
以“I”开头令人困惑,对我来说,它表示指向接口的指针,但我看到它指向Person
。这是 C++ 中的约定吗?
@Mary - 对于 COM(以及在其他平台/语言中),有一个约定接口以 I 开头。真正的接口名为 IPerson(在 C++ 级别,它是一个抽象的纯虚拟类,在二进制级别和 C 级别,它是一个结构),IPersonPtr 是一个由#import 指令构建的包装器(您必须使用 Visual Studio 来查看它)。在 COM 中,您只处理接口,但您使用的工具(此处为#import)可以添加许多其他概念。
@SimonMourier 我尝试了第二个变体,但在 ConsoleApplication1.exe 中的 0x76BCC5AF 处出现未处理的异常:Microsoft C ++ 异常:内存地址 0x0040F8F0 处的 _com_error(添加屏幕,但 VS 是俄语)。我如何破译和修复它? =)
@donax - 可能是您的 COM 对象有问题。以上是关于将应用程序从 VB 重写为 C++ 并得到错误 0070的主要内容,如果未能解决你的问题,请参考以下文章