将应用程序从 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 的成员来为你做这件事。因为它是一个指针(或类似指针的对象),您将使用-&gt; 而不是. 访问成员。 【参考方案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的主要内容,如果未能解决你的问题,请参考以下文章

C++ 库在 vb6 中有效,但在 c# 中无效

找不到从 VB6 调用的 C++ DLL 程序

我正在将 348k 行数据从 Excel 导入到 VB.net SQL。我得到这个错误:超时已过期

将 SQL 命令从 vb .net 转换为 C#

在 C# 中实例化一个数组 - 从 VB 转换 [重复]

将 VB Date() 和 DateAdd 函数转换为 PHP