【问题标题】:VBA can't find C# dll entry pointVBA 找不到 C# dll 入口点
【发布时间】:2015-07-19 10:40:59
【问题描述】:

我在 C# 中创建一个 dll,它在调用单个函数 runSimulation() 时运行模拟。应从 VBA 调用此 dll,因为某些参数值在 Excel 中作为输入给出。这是我使用的代码。

C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using RGiesecke.DllExport;

namespace Simulation
{
    public static class Simulation
    {
        [ComVisible(true)]
        [DllExport("runSimulation", CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.SysInt)]
        public static int runSimulation()
        {
            // Do simulation

            return 0;
        }
    }
}

以上代码编译为类库,x64为Platform Target,返回Simulation.dll。

VBA:

Public Declare Function runSimulation Lib "Simulation.dll" () As Long

Sub Run_DLL()
ChDir (ActiveWorkbook.Path)
Dim returnValue As Long
returnValue = runSimulation()
End Sub

运行 Visual Basic 代码返回

运行时错误 453: 'Can't find DLL entry point runSimulation in 模拟.dll'

当它尝试调用 runSimulation() 时。

作为参考:我试过用

[DllExport("runSimulation", CallingConvention = CallingConvention.StdCall)]

相反,但这也不起作用。我还尝试使用https://www.linkedin.com/grp/post/40949-258782989 中给出的建议,但它给了我同样的错误。

【问题讨论】:

  • 您确定不需要将其编译为 x86,因为您是从 VBA 系统(我认为默认为 32 位)调用它吗?
  • 您是否创建了 *.tlb 文件?
  • 如果您以 C 风格函数而不是 COM 函数导出它,那么您应该取消 [ComVisible] 属性。它可能不会伤害任何东西(因为静态方法无论如何都不能被 COM 使用)但它看起来令人困惑。
  • COM 类,COM 互操作应该可以工作。 OP 试图调用它,就好像它是一个 C 风格的函数。除非 OP 使用 64 位 Office 应用程序,否则无法使用 64 位 DLL。
  • @PanagiotisKanavos COM 不支持静态方法,因此该方法不能在 COM-Interop 中使用。我不知道 class 是否是 COM 可见的,但充其量它没有 COM 可见的方法。

标签: c# vba dll com-interop


【解决方案1】:

通过 C# 中的接口公开 Simulation 类,我设法在 VBA 代码中调用了“runSimulation”函数:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace NSSimulation
{
    public interface ISimulation
    {
        int runSimulation();
    }

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    public class Simulation : ISimulation
    {
        [ComVisible(true)]
        public int runSimulation()
        {
            return 0;
        }
    }
}

然后重新编译您的项目并使用“tlbexp.exe”从 Visual Studio 命令提示符导出重建的库:

tlbexp.exe SimulationLib.dll /out:"SimulationLib.tlb" /win64

然后在 Excel 中打开 Visual Basic 编辑器,通过“Tools->References->Browse”添加对“SimulationLib.tlb”的引用。验证

Public x As New SimulationLib.Simulation

Sub test()
   MsgBox x.runSimulation
End Sub

【讨论】:

  • 我收到 Class not registered 错误,我猜这是因为 regasm 没有在程序集本身上运行,并且 Register for COM interop 没有在 VS 中选择。
猜你喜欢
  • 2012-12-08
  • 2011-06-07
  • 2017-10-22
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 2012-03-13
  • 2019-07-02
相关资源
最近更新 更多