2

I am attempting to use Excel VBA's ability to access and use functions from DLL files.

example:

Private Declare Function funcName Lib _
"<filePath\File.dll>" _
(ByRef a As Double, ByRef b As Double) As Double

Following the instructions from Mircosoft's tutorial on how to create a DLL file, leads to 3 warnings (C4273) when I try to build the project, for the 3 functions declared:

'MathLibrary::Functions::Add': inconsistent dll linkage,
'MathLibrary::Functions::Multiply': inconsistent dll linkage,
'MathLibrary::Functions::AddMultiply': inconsistent dll linkage

When the VBA in Excel tries to access the created .dll file from this tutorial, it produces a runtime error (453): 'Can't find DLL entry point Add in "path\file.dll".


I am a novice when it comes to the C\C++ language. I have spent over 6 hours of:

  • trying to make tweaks to the vanilla tutorial
  • starting over
  • googling for help, and similar issues
  • making tweaks to the statements within VBA

And yet I feel further from a solution.

I am running 32-bit Excel on 64-bit Windows.


Any help would be much appreciated :)


Edit

Code Files (as requested):

MathLibrary.cpp

// MathLibrary.cpp : Defines the exported functions for the DLL application.
// Compile by using: cl /EHsc /DMATHLIBRARY_EXPORTS /LD MathLibrary.cpp  

#include "stdafx.h"  
#include "MathLibrary.h"  

namespace MathLibrary
{
    double Functions::Add(double a, double b)
    {
        return a + b;
    }

    double Functions::Multiply(double a, double b)
    {
        return a * b;
    }

    double Functions::AddMultiply(double a, double b)
    {
        return a + (a * b);
    }
}

MathLibrary.h

// MathLibrary.h - Contains declaration of Function class  
#pragma once  

#ifdef MATHLIBRARY_EXPORTS  
#define MATHLIBRARY_API __declspec(dllexport)   
#else  
#define MATHLIBRARY_API __declspec(dllimport)   
#endif  

namespace MathLibrary
{
    // This class is exported from the MathLibrary.dll  
    class Functions
    {
    public:
        // Returns a + b  
        static MATHLIBRARY_API double Add(double a, double b);

        // Returns a * b  
        static MATHLIBRARY_API double Multiply(double a, double b);

        // Returns a + (a * b)  
        static MATHLIBRARY_API double AddMultiply(double a, double b);
    };
}

stdafx.h

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once

#include "targetver.h"

#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>

// TODO: reference additional headers your program requires here

targetver.h

#pragma once

// Including SDKDDKVer.h defines the highest available Windows platform.

// If you wish to build your application for a previous Windows platform,
//     include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support 
//     before including SDKDDKVer.h.

#include <SDKDDKVer.h>

VBA Module

Private Declare Function Add Lib _
"c:\<Path>\MathLibrary.dll" _
(ByRef a As Double, ByRef b As Double) As Double

Sub useAddXL()
    MsgBox Add(1, 2)
End Sub
carl13
  • 69
  • 1
  • 1
  • 7
  • Have you defined the `MATHLIBRARY_EXPORTS` symbol in your **MathLibrary** project? – Phil Brubaker May 23 '17 at 01:50
  • When are you getting the warnings? when building the dll? Could you post the whole code (including _VBA_ or if possible a simple _VB_ script to strip out _Excel_ in order to reduce complexity)? As a remark "access and use functions": a method cannot be simply called as a function (via `GetProcAddress`) because it needs its context (the class). Also, I don't think that _VBA_ supports C++ compiler name mangling. – CristiFati May 23 '17 at 09:40
  • @PhilBrubaker, No, I have not defined the `MATHLIBRARY_EXPORTS` symbol; but, according to the [Microsoft tutorial](https://learn.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp): "By default, the New Project template for a DLL adds PROJECTNAME_EXPORTS to the defined preprocessor symbols for the DLL project" – carl13 May 23 '17 at 20:58
  • @CristiFati, Following the [Microsoft tutorial](https://learn.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp): after "building the solution" in step 5, when I go to the **Error List** window, it displays the `inconsistent dll linkage` [error](https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4273) for the 3 functions. – carl13 May 23 '17 at 21:04
  • @carl13 I was able to reproduce the same [Compiler Warning (level 1) C4273](https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4273) error by following the same [Walkthrough: Creating and Using a Dynamic Link Library (C++)](https://msdn.microsoft.com/en-CA/library/ms235636.aspx) tutorial and botching the `MATHLIBRARY_EXPORTS` with a simple misspelling. So for example, if you created a project named "MyMathLibrary", even with properly-named source files, you could experience this problem. I'd recommend walking through again, no problems on VS2015. – Phil Brubaker May 24 '17 at 02:26
  • The _inconsistent dll linkage_ message is clearly because of the right macro name not being defined. [\[SO\]: This answer](https://stackoverflow.com/questions/30581837/linker-error-when-calling-a-c-function-from-c-code-in-different-vs2010-project/30583411#30583411) contains some details about exporting (_C_) symbols. However, after you'll get past this error, I'm curious if it'll work. As a note, in order to see a *.dll*s exported symbols, use [DependencyWalker](http://www.dependencywalker.com). – CristiFati May 24 '17 at 07:52
  • @PhilBrubaker, what do you mean you were able to recreate the error by "_... botching the `MATHLIBRARY_EXPORTS` with a simple misspelling_"? The last time I followed this tutorial, I literally copied & pasted the code from the tutorial; I couldn't have _botched_ the spelling of `MATHLIBRARY_EXPORTS` I'm not sure what you mean in your 2nd sentence. The macro name "**str_EXPORTS**", what is '**str**' suppose to be? I may download VS2015, but I don't see that helping my understanding of this problem. **Thank you for your reply.** – carl13 May 25 '17 at 00:55
  • @CristiFati, thank you for the [DependencyWalker](http://www.dependencywalker.com/) suggestion. Using your suggestion on the created DLL from the tutorial, I get this warning `Error: At least one module has an unresolved import due to a missing export function in an implicitly dependent module.` `Error: Modules with different CPU types were found.` So, if I add `#define MATHLIBRARY_EXPORTS` to the top of `MathLibrary.cpp` (so that the ~symbol is defined), I get this error after I rebuild: `'MATHLIBRARY_EXPORTS': macro redefinition` – carl13 May 25 '17 at 01:00
  • @CristiFati, **EDIT** thank you for the [DependencyWalker](http://www.dependencywalker.com/) suggestion. Using your suggested program on the created DLL from the tutorial, I get this warning `Error: At least one module has an unresolved import due to a missing export function in an implicitly dependent module.` `Error: Modules with different CPU types were found.` – carl13 May 25 '17 at 01:10
  • @CristiFati, **EDIT:** I looked at you SO link. What I got from it was to add `#define MATHLIBRARY_EXPORTS` to the top of `MathLibrary.cpp` (so that the ~symbol is defined), but now I get these errors ([C4003](https://msdn.microsoft.com/en-us/library/zf9t054c.aspx), [C4603](https://msdn.microsoft.com/en-us/library/bb514078.aspx)) after I rebuild: `'MATHLIBRARY_EXPORTS': macro redefinition` , and `'MATHLIBRARY_EXPORTS': macro is not defined or definition is different after precomplied header use` – carl13 May 25 '17 at 01:13
  • Sorry I knew after that wasn't entirely clear. In a nutshell, I followed the steps in the tutorial using VS 2015 (though the VS version shouldn't matter) and it built fine – Phil Brubaker May 25 '17 at 01:17
  • Then I went to the header file and misspelled MATHLIBRARY_EXPORTS so that the second #define of MATHLIBRARY_API was effective instead of the first (dllimport instead of dllexport). This recreated the warning you mentioned. – Phil Brubaker May 25 '17 at 01:20
  • 'str' as you mention should be 'MATHLIBRARY'. – Phil Brubaker May 25 '17 at 01:24
  • Don't worry about the _DependencyWalker_ error. It usually happens when there's a mismatch between its architecture and the target module's (32/64 or viceversa). Anyway in spite of that error it still shows the exported symbols (if any) in the right mid section. – CristiFati May 25 '17 at 08:41

1 Answers1

1

I'm going to post this in a solution, as it doesn't fit in an comment.

The inconsistent dll linkage warning: I copied your exact code from the question as it is at this point (it might change in the future), and placed it in a newly created VStudio 2015 project:

  • Configuration type: Dynamic Library (.dll)

  • Using precompiled headers (although, I usually don't do it)

The project compiled with no warnings, if I define MATHLIBRARY_EXPORTS either:

  • In the MathLibrary.cpp file #define MATHLIBRARY_EXPORTS (before #include "MathLibrary.h")

  • As a project setting: adding it under Project Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions (next to other macros, separated by semicolons (;))

The only thing that I can imagine for you to still get the warning when building yours, is because you are defining the macro for the wrong configuration.
Example: you are building your project for Debug - x86, but you define the macro for Release - x86 (or Debug - x64).
You must check (it would be better select All Platfroms and All Configurations, and only define the macro once) that build configurations and settings configurations match, like in the image below:

Img0

But anyway, this warning is benign, the .dll is still built, and the symbols exported.

Going further, in your VBA module you declare the function name Add (plain). Based on the error message:

Can't find DLL entry point Add in "path\file.dll"

as I specified on one of my comments, I don't think that Excel is able to import C++ style exports because of [MS.Docs]: Decorated Names (C++ name mangling). While it searches for Add, your .dll exports the following symbols as shown in the (Dependency Walker) image below (you can play with the highlighted button and see how Dependency Walker is able to demangle those names):

Img1

Those (gibberish) names you should import from Excel, but I doubt that's possible. As a workaround you could either:

  • Drop the C++ features (the class and the namespace) and define and export 3 simple functions

  • Write 3 C functions (wrappers over the 3 methods), and export the functions not the methods

[SO]: Linker error when calling a C function from C++ code in different VS2010 project (@CristiFati's answer) contains all the details (pay attention at extern "C": [MS.Docs]: extern (C++)).

CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • 1
    Welp, following your steps, I tried different combinations of having the definition in the file (before the `#include`) and adding it to the _Project Properties_. In the end, I have no definition within the file, AND the definition in the _Project Properties_. **Now there are no errors** after the project is rebuilt. Perhaps the definition was not in the _Project Properties_ before. Either way, **You are correct** that VBA does not recognize the mangled names. And it seems I can not specify the mangled names (syntax error). **Thank you for your help :D** – carl13 May 25 '17 at 20:55
  • So, were you able to export 3 _C_ style functions from the _.dll_ and import them in _VBA_? – CristiFati May 25 '17 at 21:04
  • I'm fairly certain that the functions _exported_; using Dependency Walker, it seems the function names are quite mangled (eg. "?Add@Functions@MathLibrary@@SANNN@Z"). – carl13 May 26 '17 at 22:32
  • **EDIT** I'm fairly certain that the functions _exported_; using [Dependency Walker](http://www.dependencywalker.com/), it seems the function names are _quite mangled_ (eg. `?Add@Functions@MathLibrary@@SANNN@Z`). VBA doesn't accept this name, with or without quotes (Compiler error: Expected identifier). If I remove the `?` the ~compiler seems to stop reading the name at the `@` and starts checking for the key work `Lib`, but finds `Functions`. – carl13 May 26 '17 at 22:39
  • It works "manually" importing it from _C_. Although the symbols that you are trying to export, are methods in a class, there's no _OOP_ (_C++_) involved, they are basically 3 functions wrapped in a class. Declare and export them as simple functions: `Add`, `Multiply` and `AddMultiply` (lose the class and namespace). – CristiFati May 26 '17 at 23:24