Использование C ++ DLL в Excel VBA

1

Я создал MathFuncsDll.dll с https://msdn.microsoft.com/de-de/library/ms235636.aspx без проблем. Я могу использовать математические функции в другом проекте C++ и без проблем.

Теперь я хочу использовать эти функции в Excel VBA. Я пытался:

Public Declare Function DLL_Import_Add Lib "C:\Users\User\Desktop\MathFuncsDll.dll" Alias "Add" (ByVal a As Double, ByVal b As Double) As Double

Sub test()
    MsgBox DLL_Import_Add(2.1, 3.3)
End Sub

Но я получаю Run-time error '453' Точка входа в DLL не может быть найдена.

Как я могу решить эту проблему?

MathFuncsDll.h:

// MathFuncsDll.h
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif

namespace MathFuncs
{
    // This class is exported from the MathFuncsDll.dll
    class MyMathFuncs
    {
    public:
        // Returns a + b
        static MATHFUNCSDLL_API double Add(double a, double b);
        // Returns a - b
        static MATHFUNCSDLL_API double Subtract(double a, double b);
        // Returns a * b
        static MATHFUNCSDLL_API double Multiply(double a, double b);
        // Returns a / b
        // Throws const std::invalid_argument& if b is 0
        static MATHFUNCSDLL_API double Divide(double a, double b);
    };
}

MathFuncsDll.cpp:

// MathFuncsDll.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "MathFuncsDll.h"
#include <stdexcept>
using namespace std;
namespace MathFuncs
{
    double MyMathFuncs::Add(double a, double b)
    {
        return a + b;
    }
    double MyMathFuncs::Subtract(double a, double b)
    {
        return a - b;
    }
    double MyMathFuncs::Multiply(double a, double b)
    {
        return a * b;
    }
    double MyMathFuncs::Divide(double a, double b)
    {
        if (b == 0)
        {
            throw invalid_argument("b cannot be zero!");
        }
        return a / b;
    }
}
Теги:
excel-vba
excel

1 ответ

4
Лучший ответ

Я предполагаю, что вы знаете, что вы делаете при вызове библиотеки C++ из VB-программы, я имею в виду соглашение о вызове.


Проблема заключается в том, что C++ имена искажаются.

Если вы посмотрите на имена экспортируемых функций (например, с dumpbin/EXPORTS MathFuncsDll.dll, они выглядят примерно так:

ordinal hint RVA      name

      1    0 00001000 ?Add@MyMathFuncs@MathFuncs@@SAHHH@Z
      2    1 00001030 ?Divide@MyMathFuncs@MathFuncs@@SAHHH@Z
      3    2 00001020 ?Multiply@MyMathFuncs@MathFuncs@@SAHHH@Z
      4    3 00001010 ?Subtract@MyMathFuncs@MathFuncs@@SAHHH@Z

Мой результат будет отличаться от вашего, но достаточно показать, что нет простых имен, таких как " Add.

Обычно вы избегаете этого беспорядка с использованием модификатора extern "C".
С компилятором Microsoft имена классов memebers кажутся всегда искалеченными, поэтому здесь бесполезно.

Вы можете обойти это четырьмя способами:

1. Определите файл DEF который переименовывает функции

LIBRARY MathFuncsDll
EXPORTS
   Add=?Add@MyMathFuncs@MathFuncs@@SAHHH@Z
   ...

2. Используйте правильный псевдоним в своей декларации VBA

Public Declare Function DLL_Import_Add Lib "C:\Users\User\Desktop\MathFuncsDll.dll" Alias "?Add@MyMathFuncs@MathFuncs@@SAHHH@Z" (ByVal a As Double, ByVal b As Double) As Double

3. Импортируйте по порядку, используя что-то вроде Alias "#1"

Public Declare Function DLL_Import_Add Lib "C:\Users\User\Desktop\MathFuncsDll.dll" Alias "#1" (ByVal a As Double, ByVal b As Double) As Double

4. Определите глобальные функции заглушки, которые вызывают их эквиваленты

extern "C" MATHFUNCSDLL_API double Add(double a, double b)
{
   return MathFuncs::MyMathFuncs::Add(a, b); 
} 

и экспортировать их.

Ничто из этого не является совершенным, имейте в виду, что искаженные имена специфичны для компилятора, если вы используете их и изменяете/обновляете компилятор, все может распадаться.

Кроме того, ординалы не фиксируются, если вы не используете файл DEF (который снова нуждается в искаженном имени).

Последний вариант полезен для изменения соглашения о вызовах и не будет изменять способ экспорта исходных функций, что позволит получить доступ к программам C++ и не C++.

  • 0
    Это оно! Я пытался Add@MyMathFuncs@MathFuncs@@SANNN@Z но я забыл ? в начале. Я также сделал это в C и определил имя функций в DLL с помощью файла DEF, и там было написано наоборот: name_in_dll = name_in_c . Это должно быть отражено в вашем ответе?
  • 1
    @TimFinnegan Ой, спасибо

Ещё вопросы

Сообщество Overcoder
Наверх
Меню