I am trying to expose a C++ DLL to Excel using mac. The DLL was written and compiled with Xcode 4 and I am using Excel 2011.
For simple functions, extern "C" does the work and I am able to use the dylib in Excel. Specifically, if the C++ code is something like
extern "C"
{
double sumC( double a, double b)
{
return a + b;
}
}
and the VBA code is:
Private Declare Function addFunction _
Lib "Macintosh HD:Users:SVM:Documents:Excel:lib:libTestDLLtoVBA.dylib" _
Alias "sumC" (ByVal a As Double, ByVal b As Double) As Double
Function Addition(a As Double, b As Double)
Addition = addFunction(a, b)
End Function
everything works fine. But, I am interested in exposing to Excel more complex code with classes defined in header files - as in the example below - and in that case Excel returns #VALUE!. My C++ code is something like this
header file:
#ifndef TestDLLtoVBA_TestFunction_h
#define TestDLLtoVBA_TestFunction_h
class AdditionVBATest{
public:
AdditionVBATest(){};
AdditionVBATest( double ){ m_AdditionResult = 0.0; }
~AdditionVBATest(){};
void setResult( double nAddition ){ m_AdditionResult = nAddition; }
double getResult(){ return m_AdditionResult; }
void addFunct( double x, double y, double &nResult );
double addFunct( double, double );
private:
double m_AdditionResult;
};
double addFunctionC( double a, double b);
#endif
cpp file:
#include <iostream>
#include "TestFunction.h"
void AdditionVBATest::addFunct(double x, double y, double &nResult)
{
nResult = 0.0;
nResult = x + y;
AdditionVBATest::setResult(nResult);
}
double AdditionVBATest::addFunct( double a, double b )
{
double nResult(0.0);
AdditionVBATest addCompute;
addCompute.AdditionVBATest::addFunct(a, b, nResult);
AdditionVBATest addResult;
return addResult.getResult();
}
And finally this is the file that contains the function I would like to expose to Excel:
#include <iostream>
#include "TestFunction.h"
extern "C"
{
double addFunctionC( double a, double b)
{
AdditionVBATest *resAddition;
double result(0.0);
result = resAddition->AdditionVBATest::addFunct(a, b);
return result;
}
}
I tried to use the same dylib in a C++ app and works fine, so I believe it is something related to exposing the library through VBA.
The VBA code I used is
Private Declare Function addFunction _
Lib "Macintosh HD:Users:SVM:Documents:Excel:lib:libTestDLLtoVBA.dylib" Alias "addFunctionC" _
(ByVal a As Double, ByVal b As Double) As Double
Function Addition(a As Double, b As Double)
Addition = addFunction(a, b)
End Function
Any help would be greatly appreciated.
This is of course not necessary but to simplify I will assume from now on that your header file and both source files are in the same directory, and that all future commands are executed in this directory. Then replace in both source files
#include "TestFunction.h"
with
#include "./TestFunction.h"
Then, compile as follows :
g++ -m32 -Wall -g -c ./TestFunction.cpp -o ./TestFunction.o
g++ -m32 -dynamiclib ./file.cpp ./TestFunction.o -o ./libTestDLLtoVBA.dylib
where
g++ is your gcc. I guess it is clang's one, on my computer it is gcc 5.2.0, but both should work fine
file.cpp is the source file containing the declaration of addFunctionC
the -m32 option asks to produce a 32 bits dylib, as excel/VBA on mac are 32 bits
Now do a nm -gU libTestDLLtoVBA.dylib and you will see a line with _addFunctionC showing that the function addFunctionC is exported indeed.
In the VBA, declare as follows :
Declare Function addFunctionC Lib "/Path/to/your/libTestDLLtoVBA.dylib" (ByVal x As Double, ByVal y As Double) As Double
Function Addition(a As Double, b As Double)
Addition = addFunction(a, b)
End Function
and it should work. This was a great source of inspiration.
Now, if you don't want to used command line and want to use XCode for instance, I would say that the only thing you have to take care of is to ensure that XCode produces a 32 bits dylib, as excel/VBA are 32 bits only on mac OS X. I really think that this 32 bits stuff is your problem.
You likely want to read up on COM automation objects. Sometimes known as "OLE" or "ActiveX". It's essentially a way to expose classes and objects written in C++ to other programming languages.
For scripting environments (VBA and Javascript), the traditional way to do this is by registering a COM object that exposes an IDispatch interface.
Some links to get you started:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms221375(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms221326(v=vs.85).aspx
Don't get hung up on the details of "controls" and embedded UI windows. Foucs on getting a simple COM object class and interface declared in an IDL, generate a typelib, implement a C++ class that implements the interface and IDispatch. ATL (Active Template Library) makes this stuff easy.
Related
I am trying to use a Visual C++ dll in a VB.NET windows application, both created in VS2010. In the Windows project I can successfully add the dll to my references but only functions without pointer arguments are usable in the program and visible in the object browser. I borrowed a simple example I found and changed one of the function arguments to be a pointer.
header file:
// TestDLL.h
using namespace System;
namespace MathFuncs
{
public ref class MyMathFuncs
{
public:
static double Add(double *a, double B);
static double Subtract(double a, double B);
static double Multiply(double a, double B);
static double Divide(double a, double B);
};
}
cpp file
// TestDLL.cpp
// compile with: /clr /LD
#include "TestDLL.h"
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 gcnew DivideByZeroException("b cannot be zero!");
}
return a / b;
}
}
The dll compiles successfully with no warnings. When I reference the dll in a simple windows form I get the error:
"Error 1 'Add' has a return type that is not supported or parameter types that are not supported."
If I remove the pointer the dll works fine. From other forums I thought the calling convention might be a problem and tried using __stdcall but I got another error saying reference classes can't use __stdcall.
I also tried not referencing the dll and instead declaring the dll functions from a module in the windows application. I got an error saying "entry point not found" which I think is because C++ decorates the function name. I tried dumpbin.exe/EXPORTS "dll PATH" but it would not show the decorated function names. I have also tried creating an module definition file and using extern "c" although I most likely didn't use them properly. All solutions I have found to these problems have been for unmanaged C++ but do not work for managed Visual C++.
I would rather be able to reference the dll because it seems simpler. Any insight would be greatly appreciated.
Change your definition to :
double Add(double % a, double b)
{
return a + b;
}
This compiles as ByRef and works:
The common practice in C++ is to separate declarations in .h (or .hpp) and implementation into .cpp.
I know about two main reasons ( maybe there are others ):
Compilations speed ( you do not have to recomplie everything when you change just one file, you can link it by make from pre-compiled .o files )
Forward declarations are sometimes necessary ( when implementation of class A depends on class B and implementation of class B on class A ) ... but I don't have this problem so often and usulaly I can solve it.
In case of object oriented programming it looks like this:
QuadraticFunction.h:
class QuadraticFunc{
public:
double a,b,c;
double eval ( double x );
double solve( double y, double &x1, double &x2 );
};
QuadraticFunction.cpp:
#include <math.h>
#include "QuadraticFunc.h"
double QuadraticFunc::eval ( double x ){ return c + x * (b + x * a ); };
double QuadraticFunc::solve( double y, double &x1, double &x2 ){
double c_ = c - y;
double D2 = b * b - 4 * a * c_;
if( D2 > 0 ){
double D = sqrt( D2 );
double frac = 0.5/a;
x1 = (-b-D)*frac;
x2 = (-b+D)*frac;
}else{ x1 = NAN; x2 = NAN; }
};
main.cpp :
#include <math.h>
#include <stdio.h>
#include "QuadraticFunc.h"
QuadraticFunc * myFunc;
int main( int argc, char* args[] ){
myFunc = new QuadraticFunc();
myFunc->a = 1.0d; myFunc->b = -1.0d; myFunc->c = -1.0d;
double x1,x2;
myFunc->solve( 10.0d, x1, x2 );
printf( "soulution %20.10f %20.10f \n", x1, x2 );
double y1,y2;
y1 = myFunc->eval( x1 );
y2 = myFunc->eval( x2 );
printf( "check %20.10f %20.10f \n", y1, y2 );
delete myFunc;
}
then compile it with makefile like this:
FLAGS = -std=c++11 -Og -g -w
SRCS = QuadraticFunc.cpp main.cpp
OBJS = $(subst .cpp,.o,$(SRCS))
all: $(OBJS)
g++ $(OBJS) $(LFLAGS) -o program.x
main.o: main.cpp QuadraticFunc.h
g++ $(LFLAGS) -c main.cpp
QuadraticFunc.o: QuadraticFunc.cpp QuadraticFunc.h
g++ $(LFLAGS) -c QuadraticFunc.cpp
clean:
rm -f *.o *.x
However, I find it often very inconvenient
especially, when you change code a lot ( e.g. in initial phase of development when you are not yet sure about overall structure of the whole project ).
You have to go back-and-forth all the time between .cpp and .h part of code when doing significant changes to the class structure.
You have twice as much files in the editor and in project folder which is confusing.
You have to write some informations ( like function headers or QuadraticFunc:: ) twice, where you can do many typos and inconsistencies so the compiler complains all the time ( I do such mistakes very often )
Every-time you add / remove / rename some class you have to edit Makefile, where you do a lot of other mistakes which are hard to track from the compiler output ( e.g. I often forgot to write Makefile so that the code recompiles every dependency which I edit )
From this point of view I like much more how Java works. For this reason I was writing my C++ programs simply by putting all the code (including implementation) inside .h. Like this:
#include <math.h>
class QuadraticFunc{
public:
double a,b,c;
double eval ( double x ){ return c + x * (b + x * a ); }
double solve( double y, double &x1, double &x2 ){
double c_ = c - y;
double D2 = b * b - 4 * a * c_;
if( D2 > 0 ){
double D = sqrt( D2 );
double frac = 0.5/a;
x1 = (-b-D)*frac;
x2 = (-b+D)*frac;
}else{ x1 = NAN; x2 = NAN; }
};
};
with universal default makefile like this:
FLAGS = -std=c++11 -Og -g -w
all : $(OBJS)
g++ main.cpp $(LFLAGS) -w -o program.x
( main.cpp remains the same )
However, now when I'm starting to write more complex programs, the compile time starts to be quite long when I have to recompile everything all the time.
Is there any way how to use advantages of make ( faster compile time ) and still organize program structure in the Java-like way ( everything in class body instead of separate .h and .cpp ) which I find much more convenient ?
However, now when I'm starting to write more complex programs, the compile time starts to be quite long when I have to recompile everything all the time.
One of the best points in separating header and the class file is that you don't have to compile everything.
When you have class1.h, class1.cpp, class2.h, class2.cpp, ... ,classN.h and classN.cpp, those headers are only included in the compiled objects of each class. So if your function's logic changes in class2 but your header doesn't, you'll only have to compile class2 into object file. Then you'll do the linking for all object files which produces your actual executable. Linking is FAST.
If you are building large and complex programs and find that editing the headers is the problem, consider DESIGNING your application before writing it.
Short answer: no.
Long answer: Still no.
Either you put all your code in a header file, or you use two files, where the header is included and the source file compiled on its own.
I personally have no problem with using two files. Most editors support a "two file view" - and most of them also support "jump to definition of ".
Putting all functions inside the class declaration also has another side-effect, and that is that all functions are marked inline, which can lead to the function being produced multiple times in the output binaries if the same header is included in several source files.
Although the compile time, in my experience, is not a consequence of parsing, but of the code-generation part of the compilation - which typically is the .cpp file - so if you include several large headers most likely won't matter that much.
Of course use make [or something similar] with properly defined dependencies to build your project.
C++ is C++ and Java is Java. Splitting your source code in .h- und .cpp files is part of C++'s language concept. If you don't like it you shouldn't use it.
Putting everything in one header-file is practially the same as including the .cpp file (which works but is highly inappropriate).
You should not do this when:
writing standard classes, functions,...
using the code section multiple times in bigger programs (leads to redefinition error when you include everything in main.cpp otherwise)
you want to outsource part of your program in a static/dynamic library. Pretty much every available library created works that way.
Examples: WindowsAPI (COM!!), SFML, Boost (partly) (and a lot more)
You could do this when:
the code does very simple things, e.g. Bit-shift operation (making color codes), string analysis,...
Examples: Boost (partly)
You must do this when:
Creating template classes or functions as they are generated at compiling runtime. This is one of the major and most discussed downsides on the .h/.ccp-concept, so you are not the first one to wonder about it.
Examples: STL (C++ standard template library)
First of all you have to write implementation and definition in seperated file because of readebility. İt is possible to put them into same file , but it is not readable . When writing code, write for the next contributor who will need to understand your code. That is important because the next one may be you :) Second issue is makefile . Make is to make easier compilation process not faster . So if you make change in any of your file, you don't need to make change ant make files. Thanks of make , you dont need to compile your file in order again and again.write the files once , use every time. But if you add new code file which effect compilation process ,yes you have to make change in makefile. You can more information about readability,writing definition and implementation in seperate files and the all other style issue in google c++ style guide and about makefile in gnu make manuel.
I have the Xsteam.dll file that works in all of my LABVIEW projects properly; but now I want use it (Xsteam.dll) in a simple visual C++ project (in visual studio 2013 or ...).
I dont have any other file related it (such as *.h , *.lib and etc).
I know that the Xsteam.dll written in c/c++ language and I know all of its functions and variable types of their inputs and outputs arg.
I usually use the Xsteam.dll in LABVIEW at this setting:
library name or path: c:\XSteam.dll
function name: h_pT
thread: run in UI thread
calling convention: stdcall(WINAPI)
function prototype : double h_pT#16(double arg1, double arg2);
return type : Numeric 8-byte double
arg1: Numeric 8-byte double Pass: Value
arg2: Numeric 8-byte double Pass: Value
prototype for these procedures:
MgErr Proc(InstanceDataPtr *instanceState);
How to use Xsteam.dll by a simple Vc++ program?
example:
HMODULE hModule = LoadLibrary("c:\\XSteam.dll");
typedef double (* FNPTR) (double , double );
FNPTR pfn = (FNPTR)hModule.GetProc("h_pT");
if ( NULL != pfn )
{
double result=pfn(arg1, arg2);
}
You'll need to make a header file and use dumpbin and lib to create an import library (*.lib). Look here or here.
Currently, I'm learning c++ and a question about the modularization process. Suppose I want to write a function to add two or three numbers. For that purpose I've wrote the following header file:
// Sum2.hpp
//
// Preprocessor directives; ensures that we do not include a file twice
// (gives compiler error if you do so)
#ifndef Sum2_HPP
#define Sum2_HPP
/////////// Useful functions //////////////////
// Max and Min of two numbers
double Sum2(double x, double y);
// Max and Min of three numbers
double Sum2(double x, double y, double z);
////////////////////////////////////////////////
#endif
This is just declaration. In a separate file, I specify the functions:
// Sum2.cpp
// Code file containing bodies of functions
//
#include "Sum2.hpp"
/////////// Useful functions //////////////////
// Sum of two numbers
double Sum2(double x, double y)
{
return x+y;
}
// Sum of three numbers
double Sum2(double x, double y, double z)
{
return Sum2(Sum2(x,y),z);
}
And then, in the main programm I want to use these functions:
// main.cpp
#include <iostream>
#include "Sum2.hpp"
int main()
{
double d1;
double d2;
double d3;
std::cout<<"Give the first number ";
std::cin>> d1;
std::cout<<"Give the second number ";
std::cin>> d2;
std::cout<<"Give the third number ";
std::cin>> d3;
std::cout<<"The sum is: "<<Sum2(d1,d2);
std::cout<<"The sum is: "<<Sum2(d1,d2,d3);
return 0;
}
I used g++ -c Sum2.cpp to generate the object code Sum2.o. Why is there a reference error when I want to compile and create an executable from the main code, i.e. g++ -o main main.cpp?
It is working when I compile both at same time, i.e. g++ -o main main.cpp Sum2.cpp. I thought by creating the object code Sum2.o and including the header file in main.cpp the compiler will automatically recognize the object code. Why this is not working?
// Preprocessor directives; ensures that we do not include a file twice
// (gives compiler error if you do so)
No actually, it won't give a compiler error. It just won't do anything.
As for your actual question, c++ unlike some other languages won't try to find your object files for you. You have to tell the compiler where they are at. For this application you should really compile it like so:
g++ -c main.cpp
g++ -c Sum2.cpp
g++ -o main main.o Sum2.o
The first two actually compile the code. The second links the code together to produce the executable. If you execute
g++ -o main main.cpp Sum2.cpp
The compiler will automatically run both steps for you. It works for a small project, but for larger projects you don't want to run all the steps unless something has changed.
Now, you may think that's a pain. You'd be right. That's why there are various tools like CMake, Scons, Jam, Boost.Build which are designed to make it easier to build C++ projects.
Ive built a simple dll in c++ using Visual C++ 2010 and am trying to use it in excel. The project name is "SwapFunDLL", the source files name is "swapmain" and the name of the header file containing the class and its function is "DateNTime". Ive attached them below. The code takes in two values and then uses the class function to multiply them and then returns the product (i realize the class and function arent necessary, im just doing this to learn). The function compiles with not errors however when the function is used in excel i get a value error. Could someone please help me see what im doing wrong thanks.
header:
// DateNTime.h
//Avoid need of .Def file
#ifdef SwapFunDLL_EXPORTS
#define SwapFunDLL_API __declspec(dllexport)
#else
#define SwapFunDLL_API __declspec(dllimport)
#endif
namespace DateNTime
{
class SwapFunDLL_API Date
{
double x,y;
public:
double datediff(double,double);
};
double Date::datediff(double x, double y)
{
return x*y;
}
}
Source File:
#include "DateNTime.h"
namespace DateNTime
{
double returndates(double a, double b)
{
Date Date;
return Date.datediff(a,b);
}
}
Excel Macro:
Declare Function SwapFunDLL _
Lib "C:\Users\MIKE\Desktop\c++ tial programs\SwapFunDLL\Debug\SwapFunDLL.dll" _
(ByRef x As Double, ByRef y As Double) As Double
your import declaration is wrong. Two things: the semantics and declaration of types. If you use pointers than in Excel you say ByRef, but if you use by value passing you say ByVal.
Declare this function as:
Declare Function returndates Lib "C:\Users\MIKE\Desktop\c++ tial programs\SwapFunDLL\Debug\SwapFunDLL.dll" _ (ByVal x As Double, ByVal y As Double) As Double
make your function returndates member of your class that is being exported, static member.
also make your function static and in any case you can declare this export in .def file (just simply: "returdates" it's all). After all of it this has to work unless your C++ code is OK.
also here:
double returndates(double a, double b)
{
Date Date; //<- change it, i.e: Date d; d.datediff(); does it compile?
return Date.datediff(a,b);
}
you can change the code just to test if you do everything correctly to such "test info" form:
double returndates(double a, double b)
{
return 117;
}
and try it in Excel.
Excel needs __stdcall, so make a functions declarations inside your class like this:
static double __stdcall returndates(double a, double b);
then define it in .cpp file as:
SwapFunDLL_API double __stdcall DateNTime::Date::returndtes(double a, double b){
return 117;
}
after all these changes should be OK.