C# 如何将COM对象从VBA传递到C++;动态链接库

C# 如何将COM对象从VBA传递到C++;动态链接库,c#,c++,.net,excel,vba,C#,C++,.net,Excel,Vba,我有一个Excel/VBA应用程序,它通过DLL将重磅重传给C++。目前,我使用一长串参数在两者之间传递输入/输出,这些参数是基本数据类型及其指针。我试图重构代码的两面,使之更模块化,并认识到,有一个可以通过的公共对象,而不是从非结构化的指针列表中重新构建C++结构,将是有益的。我想尝试一下COM/.NET,这就是我所处的位置: 1) 使用C#类库创建了一个COM对象,如下所示 2) 使用regasm/codebase/tlb生成Interop.dll并注册Interop.tlb 3)在VBA

我有一个Excel/VBA应用程序,它通过DLL将重磅重传给C++。目前,我使用一长串参数在两者之间传递输入/输出,这些参数是基本数据类型及其指针。我试图重构代码的两面,使之更模块化,并认识到,有一个可以通过的公共对象,而不是从非结构化的指针列表中重新构建C++结构,将是有益的。我想尝试一下COM/.NET,这就是我所处的位置:

1) 使用C#类库创建了一个COM对象,如下所示

2) 使用
regasm/codebase/tlb生成
Interop.dll
并注册
Interop.tlb

3)在VBA中,添加一个引用:<代码>互操作.TLB,坚持将实例传递给C++ DLL函数:

// VBA
Declare Sub my_func Lib "my_func.dll" (ByRef mc as Interop.My_class)

Sub test_interop()
  Dim mc as Interop.My_class
  Set mc = New Interop.My_class
  my_func mc
End Sub

// my_func.cpp (exports my_func to my_func.dll)
#import "Interop.tlb"

void __stdcall my_func(Interop::IMy_classPtr icp) { ... }
VBA似乎可以创建实例,但调用my_func会导致Excel崩溃。我可以在调试模式下看到,从Excel接收到的
icp
的值等于
VarPtr(mc)
,而不是
ObjPtr(mc)
,我认为这是接口的地址。因此,我尝试将其更改为
my_func(Interop::my_class*mcp)
,我至少可以在不崩溃的情况下进出函数,但我的_类似乎没有可用的功能。该功能似乎被称为
\u My_class
,因此我尝试了
My_func(Interop::\u My_class*mcp)
,但一旦尝试与
mcp
交互,我就会崩溃。与
my\u func(Interop::\u my\u classPtr mcp)的结果相同

使用原始函数,我还尝试使用VBA中的
DispCallFunc
ObjPtr(mc)
直接传递到“icp”。同样,我可以进出函数,但当我尝试与对象交互时崩溃了。实际上,我可以在不崩溃的情况下读取它(虽然不是正确的值),但当我尝试写入它时,出现了以下错误:
运行时检查失败#0-ESP的值未在函数调用中正确保存。这通常是调用使用一种调用约定声明的函数,并使用另一种调用约定声明的函数指针的结果。

这里没有选择了,我想知道我是否已经接近了,这是不可能的,还是这不是正确的方法


< >我也直接在C++中测试了C类类库。我可以使用<代码> COCCREATEAUTION/CODE >创建一个实例,并通过接口与之交互,因此如果从C++侧启动,它似乎可以正常工作。

< P> com和IOPO做一些内部管道将您绊倒在这里。我相信您希望按照以下思路做一些事情:

 dim myObj as Interop.IMyClass    # Note: Interface, not the class
 set myObj = new Interop.MyClass
 myObj.name = "My Name"
 myObj.age  = 69
 myObj.job  = "Chief Stamp Licker"

 my_func myObj
然后在我的函数中:

 std::cout << "Name: " << pMyObj->name() << ", "
           << "Age : " << pMyObj->age()  << ", "
           << "Job : " << pMyObj->job()  << std::endl;
…这将使您更容易/更快地实施,但扩展的灵活性和时间要少得多。介于两者之间的内容可能适合您-例如,setPerson和setOccupation接受多个参数


不能直接写入myObj变量的原因是,Visual Basic运行时中的“myObj”不是对象,它是指向代理对象的接口,由Visual Basic运行时环境、COM子系统、DCOM子系统、C#interop层或其组合制作,取决于你的COM对象注册、线程模型以及Excel是如何初始化的(你不能控制)。V/BA VBA不会让你通过C++编译器自动生成的智能指针类型,这是崩溃的。您也永远无法获得指向对象的指针,COM只实现接口指针。VBA试图隐藏的东西,因为它不直接支持接口。最安全的方法是将参数声明为接口的
IUnknown*
和QI。我想你需要把ByRef换成ByVal。好的,谢谢你,汉斯,我正在尝试。还想知道它最终是否会比我最初的非结构化方法更好……宾果!你成就了我的一天:-)我实际上已经设置了get&sets,我只是没有注意到VBE中的
.IMyClass
选项。这正是我所希望的。看来我最后两天的工作并没有白费。但愿我在伦敦能给你买一品脱!非常感谢,乔治
 std::cout << "Name: " << pMyObj->name() << ", "
           << "Age : " << pMyObj->age()  << ", "
           << "Job : " << pMyObj->job()  << std::endl;
myObj.setProperties("My Name", 69, "Chief Stamp Licker")
my_func myObj