UnmanagedExports函数参数 - 导致VBA 49错误的DLL调用约定

时间:2018-01-25 20:49:27

标签: c# excel-vba dllexport function-parameter unmanagedexports

我无法让我的C#Dll与我的Excel宏启用电子表格一起调用Dll中的函数。如果函数没有参数,我可以调用该函数,能够返回预期的值。但是当我向函数添加输入参数时,我无法从VBA获得成功的Dll调用。

我的C#模块的总和如下:

using System;
using System.Runtime.InteropServices;
using RGiesecke.DllExport;

namespace RSExternalInterface
{
    public class RSExternalInterface
    {
        [DllExport("add", CallingConvention = CallingConvention.Cdecl)]
        public static int TestExport(int left, int right)
        {
            return left + right;
        }
    }
}

我的VBA代码如下。

模块声明:

Declare Function add Lib "C:\Program Files\RS\RSExternalInterface.dll" (ByVal Left As Integer, ByVal Right as Integer) As Integer

在按钮的click事件子区域内调用上面的函数,如下所示:

result = add (5, 7)

执行上述行的那一刻,错误49出现了。

我尝试了以下内容:

  1. 删除了" ByVal"在VBA函数声明中
  2. 在[DllExports ...]
  3. 之后删除并添加了C#功能中的装饰
  4. 确保我定位到正确的CPU平台
  5. 删除声明中的参数并调用以确保可以访问DLL函数。
  6. 我做错了什么?

1 个答案:

答案 0 :(得分:0)

我很惊讶“来自问题标题的呼叫会议”和来自 C#代码的CallingConvention没有响铃(虽然我不统治在 MS 方面发出误导性错误消息。)

调用约定就像执行子例程时的协议,在:

之间
  • callee - 例程(函数,过程(或不返回任何内容的函数,或返回void))
  • 调用者 - 调用/执行被调用者
  • 的代码(也是一个子例程 - 可能是main

并确定:

  1. 谁处理(推送 / pop )堆栈上的函数参数(被调用者 / 调用者)执行它
  2. 堆叠上的参数顺序(右 - >左左 - >右
  3. 由于#1。,2方(被叫方 / 来电与同步非常重要关于调用约定,否则它们会在彼此的脚趾上设置,并且堆栈最终会被破坏。 “ Bad DLL Calling Convention ”就是指这一点:2是同步。

    • 你得到没有参数的函数的正确行为,因为没有什么可以推送 / pop 到堆栈中 - 这并不意味着没有没有错误;错误在那里,但没有遇到
    • 更多详情:[MSDN]: Argument Passing and Naming Conventions。请注意__stdcall__cdecl之间的差异,并注意它们适用于 32位( x86 )架构 AFAIK (也由错误备份), Excel 可执行文件(整个 MSOffice )为32位
    • 根据[MSDN]: DllImportAttribute.CallingConvention Field(我认为它也适用于DllExport):
        

      您将此字段设置为其中一个CallingConvention枚举成员。 CallingConvention字段的默认值为Winapi,而默认值为StdCall约定。

    我拿了你的代码,并用它玩了一点。

    code.cs

    using System;
    using System.Runtime.InteropServices;
    using RGiesecke.DllExport;
    
    
    namespace RSExternalInterface
    {
        public class RSExternalInterface
        {
            [DllExport("add")]
            public static int TestExport(int left, int right)
            {
                int ret = left + right;
                String s = String.Format("C# Func - add: {0} + {1} = {2}", left, right, ret);
                Console.WriteLine(s);
                return ret;
            }
    
            [DllExport("dbl", CallingConvention = CallingConvention.Winapi)]
            public static int TestExport1(int value)
            {
                int ret = value * 2;
                String s = String.Format("C# Func - dbl: {0} * 2 = {1}", value, ret);
                Console.WriteLine(s);
                return ret;
            }
    
            [DllExport("none", CallingConvention = CallingConvention.StdCall)]
            public static void TestExport2(int value)
            {
                String s = String.Format("C# Func - none: {0}", value);
                Console.WriteLine(s);
            }
    
        }
    }
    

    main.vb

    Module main
    
        Declare Function add Lib "CsDll.dll" (ByVal Left As Integer, ByVal Right As Integer) As Integer
        Declare Function dbl Lib "CsDll.dll" (ByVal Value As Integer) As Integer
        Declare Sub none Lib "CsDll.dll" (ByVal Value As Integer)
    
        Sub Main()
            Console.WriteLine("64 bit OS: {0}{1}64 bit process: {2}{1}", Environment.Is64BitOperatingSystem, Environment.NewLine, Environment.Is64BitProcess)
            Dim i As Integer
            none(-7659)
            i = dbl(78)
            i = add(22, -13)
    
        End Sub
    
    End Module
    

    备注

    • 我无法构建它并在 Excel 中运行它,所以我尝试了2 nd 最好的事情:从 VB 。请注意,我既没有 C#也没有 VB
    • 一开始(正如我在评论中所述),我无法从 C# .dll 中导出任何内容。查看 UnmanagedExports.nuspec nupkg 的一部分):
        
          
      • 您必须将平台目标设置为x86,ia64或x64。 AnyCPU程序集无法导出函数。
      •   
    • 平台任何CPU VStudio 默认设置)更改为 x64 (错误地),以及所有内容运行良好(尽管CallingConvention.Cdecl),只有在设置为 x86 后才能重现问题
    • 无论如何,( C#)代码包含3种(不)指定调用约定的方法,它将起作用于 VB

    输出 VStudio 2015(社区)):

    64 bit OS: True
    64 bit process: False
    
    C# Func - none: -7659
    C# Func - dbl: 78 * 2 = 156
    C# Func - add: 22 + -13 = 9
    

    这是一个(古老的)网址,它也提到了您的错误:[MSDN]: Bad DLL calling convention (Error 49)