如何使用IDispatch从非托pipec ++调用C#的DLL?

我有一个C#DLL,我需要从非托pipeC ++调用。 我的主要问题是我的c ++代码对应于一个excel插件,可以安装excel 2003和excel 2007,当我在excel 2007中安装我的加载项,我尝试调用我的C#DLL,它工作得很好,但由于某种原因,我仍然无法find,在Excel 2003中崩溃,Excel显示我一个运行时错误信息,当debugging我的C代码,我可以看到代码失败时试图创build我的C#DLL的实例,它说,即使我注册regasm类没有注册。

这是我的C#代码:

namespace ManagedDLL { [ Guid("3C80EE60-D9B8-4daf-89BE-6C7B748F613C"), InterfaceType( ComInterfaceType.InterfaceIsDual), ComVisible(true) ] public interface ICalculator { [DispId(1)] int main(string args, IntPtr _handle); }; [ Guid("5134F342-5B7F-4db2-94F0-F450610419CF"), ProgId("myapp.CCOMEntryPoint"), ClassInterface(ClassInterfaceType.None), ComDefaultInterface(typeof(ICalculator)), ComVisible(true) ] public class COMEntryPoint : ICalculator { public int main(string args, IntPtr _handle) { string[] _args = args.Split(new char[] { ':' }); Program.handle = _handle; return Program.Main(_args); } } } 

而在C ++中,我所做的是导入在使用regasm注册我的C#dll时生成的.tlb文件,如下所示:

 \#import "..\bin\release\ManagedDLL.tlb" raw_interfaces_only using namespace ManagedDLL; . . . int callMyDll() { long handle = 0, result = 0; BSTR args; HRESULT hr = CoInitialize(NULL); ICalculatorPtr pICalc(__uuidof(COMEntryPoint)); pICalc->main(bstrStr, handle, &result); return result; } 

但正如我之前提到的,这个代码不适用于Excel 2003,所以我的问题是:

  1. 我在做错误的方式,我宣布我的C#DLL,这是在Excel 2003中导致我的问题?
  2. 就像现在一样,我的C#DLL可以被认为是一个ActiveX对象?
  3. 我怎样才能以另一种方式从C ++调用我的C#DLL? 比如使用IDIspatch

谢谢

我以前有类似的问题。 我没有从C ++调用C#,但概念是相同的。

我不得不通过COM加载一个.NET DLL到主机应用程序,这看起来像你正在做的事情。 问题是主机应用程序(在你的情况下Excel)加载.NET运行时1.1。 我们的dll是为.NET 2.0编译的。

可能是因为Excel 2003加载了1.1运行时,而2007则加载了更新的版本。 看看这个论坛: Excelselect错误的.NET运行时 。

您也可以使用MSBee来testing这个目标1.1运行时,然后尝试加载您的DLL在Excel 2003中。

我不是C ++编码器,所以我不能评论这个部分,而是从C#端回答:

“我在做错误的方式,我宣布我的C#DLL,这是在Excel 2003中导致我的问题?”

不,你的属性使用看起来完全正确。 做得好。

“就像现在一样,我的C#dll可以被认为是ActiveX对象吗?”

通过编译您显示的属性,然后通过RegAsm注册,您已经创build并正确地将您的程序集暴露给COM,这正是您想要的。 (术语“ActiveX”通常用于引用COM 控件 ,而您的类不是控件。)

“我怎样才能以另一种方式从C ++调用我的C#DLL?比如使用IDIspatch。”

您正在使用[InterfaceType(ComInterfaceType.InterfaceIsDual)]属性,这意味着该接口通过IDispatch暴露于早期绑定和后期绑定。

简而言之,我不知道这里有什么问题,所以我会尝试使用dequadin的想法来检查正在加载的.NET Framework版本是否在您正在构build的框架之上或之上。

如果不是这样的话,我唯一能想到的是事实上,你正在经历一次直接的崩溃,没有一个可以修复的错误,向我暗示,在注册的界面和主界面之间可能会有某种不一致调用者编译的接口。 发生这种情况的原因是,如果更改了接口,GUID不会改变 – 您已经通过属性显式地设置了GUID – 因此,如果接口更改完全没有重新构build,并且从下到上重新注册,所有的地狱都打破了。 因此,如果以任何方式更改了接口,则需要重新构buildC#程序集,重新注册RegAsm,然后重新编译引用它的C ++加载项。

这只是我最好的猜测。 如果您使用的是相同的精确程序集,则不能解释Excel 2003与2007年问题。 总之,很难知道什么是错误的,因为你的C#代码看起来100%干净。

迈克