C++ How to export a static class member from a dll? - c++

//API mathAPI.h, both in Dll.cpp and Test.cpp
#ifdef __APIBUILD
#define __API __declspec(dllexport)
//#error __APIBUILD cannot be defined.
#else
#define __API __declspec(dllimport)
#endif
class math
{
public:
static __API double Pi;
static __API double Sum(double x, double y);
};
// Dll.cpp __APIBUILD is defined
#include "mathAPI.h"
double math::Pi = 3.14;
double math::Sum(double x, double y)
{
return x + y;
}
// Test.cpp __APIBUILD not defined
#include <iostream>
#pragma comment(lib, "dll.lib")
#include "mathAPI.h"
int main()
{
std::cout << math::Pi; //linker error
std::cout << math::Sum(5.5, 5.5); //works fine
return 0;
}
Error 1 error LNK2001: unresolved external symbol "public: static double Math::Pi" (?Pi#Math##2NA)
How do i get this to work?

The better solution to get your Pi value is to create a static method to init and return it, like the following in your DLL.cpp:
#include "mathAPI.h"
// math::getPi() is declared static in header file
double math::getPi()
{
static double const Pi = 3.14;
return Pi;
}
// math::Sum() is declared static in header file
double math::Sum(double x, double y)
{
return x + y;
}
This will prevent you of uninitialised value Pi, and will do what you want.
Please note that the best practice to initialize all static values/members is to initialize them in a function/method call.

Instead of exporting members one by one, export whole class. Also, I totally don't know how this code can work - you didn't provide definition for sum() (missing class scope operator) and that's what linker should complain about (instead of math::Sum(), you defined new, global sum()).
mathAPI.h
#ifdef __APIBUILD
#define __API __declspec(dllexport)
#else
#define __API __declspec(dllimport)
#endif
class __API math //Add __API to export whole class
{
public:
static double Pi;
static double Sum(double x, double y);
};
Dll.cpp
#include "mathAPI.h"
double math::Pi = 3.14;
double math::Sum(double x, double y) //You missed 'math::' here before
{
return x + y;
}
And that's it.
EDIT
You should still get an error, though. That's because you made a typo, that I haven't noticed (and you did not post the real code!). In your Dll.cpp, you wrote:
double math::Pi = 3.14;
Although you posted something different, I am sure, that your class is named Math, not math, because linker is trying to search for:
?Pi#Math##2NA
So it is looking in class Math. This is the most probable guess. Though, I am pretty sure, that you did not post the real code, but hand-written snippet.

Related

I receive the error "expected an identifier" while creating a class with a constructor which takes parameters

Below you will find my code. First I present the header file then the corresponding cpp file. The error I receive is on the line of the constructor and states "expected an identifier" I have searched everywhere to find this error and I am stuck. It is also worth noting that I am not yet comfortable with classes in c++.
The header file:
#include <Eigen/Core>
#ifndef RIDGE_GD
#define RIDGE_GD
class RIDGE_GD
{
public:
RIDGE_GD(double lambda, double eta, double max_iter);
void fit(Eigen::MatrixXd X, Eigen::MatrixXd y);
double error();
Eigen::MatrixXd cost_grad();
void gd_step();
Eigen::MatrixXd X;
Eigen::MatrixXd y;
Eigen::MatrixXd w;
private:
double m_lambda;
double m_eta;
double m_max_iter;
};
#endif
The corresponding cpp file:
#include "RIDGE_GD.h"
#include <Eigen/Core>
RIDGE_GD::RIDGE_GD(double lambda, double eta, double max_iter)
{
m_lambda = lambda;
m_eta = eta;
m_max_iter = max_iter;
}
Eigen::MatrixXd RIDGE_GD::cost_grad(RIDGE_GD.X, RIDGE_GD.y, RIDGE_GD.w, RIDGE_GD.lambda) {};
void RIDGE_GD::gd_step()
{
}
void RIDGE_GD::fit(Eigen::MatrixXd X, Eigen::MatrixXd y)
{}
double RIDGE_GD::error()
{}
Your include guard uses the same identifier as your class name. So all instances of RIDGE_GD are replaced by nothing. The compiler sees your class as
class {
public:
(double lambda, double eta, double max_iter);
// ...
};
which is why you get the error.
Use a different identifier for your include guard. (Or change the name of your class.)
The header guard is wrong, it changes the class name to nothing:
#ifndef RIDGE_GD
#define RIDGE_GD
^^ This line changes `class RIDGE_GD` to `class `, as RIDGE_GD is defined to be empty
Instead use a proper header guard:
#ifndef RIDGE_GD_HEADER_INCLUDED
#define RIDGE_GD_HEADER_INCLUDED
...
#endif

I do not understand why it comes up with a syntax error

I am making a program in c++ class and I do not understand why this syntax error is a semicolon is not defined. If you need me to send stacktrace then, I will put it up in the comment section. I have multiple errors in this H class. I am new programmer in c++. Thank you for your contribution.
#pragma once
#ifndef CONVERT_M_TO_FT_H
#define Convert_M_to_Ft
class Convert_M_to_Ft {
private:
double feet, meters, inches, centimeters;
const double METERS_PER_FOOT;
const double INCHES_PER_FOOT;
public:
Convert_M_to_Ft();
void conversion();
void setFeetAndInches(double feet, double inches);
double getMeters();
double getCentimeters();
};
#endif
Replace
#define Convert_M_to_Ft
with
#define CONVERT_M_TO_FT_H
The problem is that the preprocessor expands
class Convert_M_to_Ft {
private:
//...
};
to
class {
private:
//...
};
otherwise.
It's because you:
#define Convert_M_to_Ft
That means that Convert_M_to_Ft will be converted to nothing in your code. Specifically this line:
public:
Convert_M_to_Ft();
Will be converted into:
public:
();
And that's probably where your syntax error is coming from. You should include the actual error with actual line numbers if that's not the only error.
You probably meant to do this on the top:
#pragma once
#ifndef CONVERT_M_TO_FT_H
#define CONVERT_M_TO_FT_H

How to define a "global" struct?

Let say I've decleared this within MyTools.h
#ifndef _MYTOOLS_
#define _MYTOOLS_
typedef struct {
// const
double LN20;
double LN40;
// methods
double NoteToFrequency(int noteNumber);
} Tool;
extern const Tool tool;
#endif // !_MYTOOLS_
For every compilation unit, there is only a global/const/unique instance of Tool. Exactly what I want.
But now: how can I define it? In the .h i've only declared it. How can I define it in .cpp? Tried somethings like:
tool.LN20 = 1.34;
But of course it doesn't works. And the method's definition?
extern doesn't define any variable it just declares it. What you wan't to achieve can be done as below:
The link Global const object shared between compilation units explains how to do it with extern const
t.h file
#ifndef _MYTOOLS_
#define _MYTOOLS_
struct Tool {
// const
double LN20;
double LN40;
double NoteToFrequency(int noteNumber);
} ;
extern const Tool tool ;
#endif // !_MYTOOLS_
t1.cpp
#include "t.h"
#include <stdio.h>
void use_tool()
{
printf("%f\n",tool.LN20);
printf("%f\n",tool.LN40);
return;
}
t2.cpp
#include "t.h"
#include <stdio.h>
const Tool tool = {.LN20 = 20.0, .LN40 = 30.2};
double Tool::NoteToFrequency(int noteNumber)
{
return 12.0;
}
void use1_tool()
{
printf("%f\n",tool.LN20);
printf("%f\n",tool.LN40);
return;
}
int main()
{
void use_tool();
use_tool();
use1_tool();
return 0;
}
Hope this helps.

Class definition in header file issues

I am receiving the following error from the compiler
./include.list.h(22) error: identifier "input" is undefined.
Here is the header file where I explicitly define input-
#ifndef INIT_H
#define INIT_H
#include "list.h"
class input{
public:
//** thermo variables **//
int N;
double nddensity;
double ndtemp;
double ndvol;
double ndside;
double ndsideh;
// ** force field variables** //
double eps;
double sigma;
double rcut;
double rv;
double rcut2;
double rv2;
double rcrv2;
input();
};
void print(input &);
double randomnumber();
void position(list &, input &, int flag);
#endif
In init.cpp, I have the class initialization:
input:: input() {
//** thermo variables **//
N = 500;
nddensity =.8;
ndtemp = 2.0;
ndvol = N/nddensity;
ndside = pow(ndvol,1.0/3.0);
ndsideh = ndside/2;
// ** force field variables** //
eps = 1;
sigma = 1;
rcut = 2.5;
rv = 1.1*rcut;
rcut2 = rcut*rcut;
rv2 = rv*rv;
rcrv2 = (rv-rcut)*(rv-rcut);
}
I can't seem to figure out why input would be undefined to void print. Any help is appreciated.
You have a circular dependency.
You can forward declare the other class, but this is still a poor design. Better to just do away with the circular dependency altogether. At second glance, do you even need to include list.h? Where are you using anything declared in it?
You include list.h before the class definition, so it's not available in that header. According to the error message, something in list.h needs a declation of the class.
You don't need a full definition of list here, so replace the #include with a forward declaration
class list;
Within list.h, you probably need a similar declaration of input; or it might be necessary to include init.h if the header does something complicated with it.

call a member of a nested structure, ERROR does not have class type

In main.C I am trying to access a nested structure member
(g.Fp1.d_status) and am getting the error:
'g.GridPt::Fp1' does not have class type
Below is my code. I can realy use some help. Thanks.
I tried stuff like g.MarchingDirection::Fp1.d_status,
g.&MarchingDirection::Fp1.d_status, ... with no luck.
//Filename: main.C
#include "GridPt.h"
int main()
{
GridPt g;
g.d_lstDistFn;
g.Fp1.d_status; \\ERROR: 'g.GridPt::Fp1' does not have class type
return 0;
}
//Filename: MarchingDirection.h
#ifndef included_MarchingDirection
#define included_MarchingDirection
struct MarchingDirection
{
MarchingDirection(double FValue);
double d_F;
int d_inOut;
char d_status;
};
#endif
//Filename: MarchingDirection.C
#include "MarchingDirection.h"
MarchingDirection::MarchingDirection(double FValue)
: d_F(FValue),
d_inOut(static_cast<int>(FValue)),
d_status('d'){}
//Filename: Grid2D.h
#ifndef included_GridPt
#define included_GridPt
#include "MarchingDirection.h"
#include <cstddef>
struct GridPt
{
GridPt();
double d_x, d_y;
MarchingDirection Fp1(double F=1.0), Fm1(double F=-1.0);
double d_lstDistFn;
};
#endif
//Filename: GridPt.C
#include "GridPt.h"
GridPt::GridPt()
: d_lstDistFn(0.0){}
You declared Fp1, Fm1 functions inside GridPt struct, they are not members
You could change to:
struct GridPt
{
GridPt();
double d_x, d_y;
MarchingDirection Fp1, Fm1;
double d_lstDistFn;
};
Initialize all your struct members shown as below:
GridPt::GridPt()
: d_x(0.0),
d_y(0.0),
Fp1(1.0),
Fm1(-1.0),
d_lstDistFn(0.0)
{}