How to create a DLL exposing a generic function? - c++

I want to expose generic Timer. The problem is I don't know why extern got underlined with red and the Visual Studio 2019 Community says "linking specification is not allowed".
Question
What is the correct syntax for extern?
Minimal Working Example
The header utilities.hpp:
#pragma once
#ifdef UTILITIES_EXPORTS
#define UTILITIES_API __declspec(dllexport)
#else
#define UTILITIES_API __declspec(dllimport)
#endif
namespace Utilities
{
template<typename F>
extern "C" UTILITIES_API void Timer(F f, unsigned int N = 1);
}
The definition file utilities.cpp:
#include "Timer.h"
#include <iostream>
#include <vector>
#include <chrono>
#include <iomanip>
using namespace std;
namespace Utilities
{
template<typename F>
void Timer(F f, unsigned int N)
{
cout << fixed << setprecision(9);
vector<unsigned int> results;
const double million = 1'000'000'000.0;
for (unsigned int i = 0; i < N; i++)
{
chrono::steady_clock::time_point begin = chrono::steady_clock::now();
f();
chrono::steady_clock::time_point end = chrono::steady_clock::now();
unsigned int interval = chrono::duration_cast<chrono::nanoseconds>(end - begin).count();
results.push_back(interval);
double elapsedTime = interval / million;
cout << "Elapsed: \t\t" << elapsedTime << " s." << endl;
}
unsigned long long sum = 0;
for (unsigned int x : results)
sum += x;
double totalElapsedTime = sum / million / results.size();
cout << "\t\t\tAverage elapsed: " << totalElapsedTime << " s." << endl;
}
}

The compiler has to know what types you use with the generic, because it basically has to make a copy of Timer that works with that type.
For an extern method, there is no way to know this, and it would have to be evaluated at runtime, which is not how generics work. It's a compiler feature.
You can make a wrapper for a specific type and make that extern.

Related

Declaring sqrt(var) as a compile time constant in c++

I have a c++ program where I need to pass the square root of a number in a for loop.
#include<random>
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include <stdlib.h>
#include <windows.h>
#include <ctype.h>
#include <omp.h>
using namespace std;
int main()
{
vector<int>inputDataBits(49); // vector of randomly generated input data bits
#ifdef printDebug
std::cout << "the input data bits are" << endl;
std::cout << "-------------------------" << endl << endl;
int var =49;
const int r=(int)sqrt(var);
float input2d[r][r];
for (int i = 0; i < r; i++)
{
for (int j = 0; j < r; j++)
{
input2d[i][j] = inputDataBits[(j %r) + (i *r)];
std::cout << input2d[i][j] << "\t";
}
std::cout << endl << endl;
}
std::cout << endl << endl;
#endif
return 0;
}
I get an error 'expression must have a constant value'. Is there a way to do this in c++?
This is the purpose of the constexpr keyword (make the value known at compile time).
constexpr int var=49;
constexpr int r=(int)sqrt(var);
Unfortunately, in the documentation sqrt() is not declared as a constexpr function.
Only gcc seems to consider it as constexpr but it is not portable.
The size of an array needs to be known at compile-time.
Instead you can use a std::vector, which has a dynamic size.
std::vector<std::vector<float>> input2d(std::vector<float>(r), r);

c++ / scope of struct

In following code, I think that structure stSameNameButDifferent is local scope definition and so no problem for it. But I got error in run-time.
(error : process crash)
Can you explain what's wrong with that code?
test_function.h
#ifndef TEST_FUNC_H_
#define TEST_FUNC_H_
void test_a();
void test_b();
#endif
main.cpp
#include <iostream>
#include "test_function.h"
using namespace std;
int main(int argc, const char** argv)
{
cout << "testing for struct scope" << endl;
test_a();
test_b();
return 0;
}
test_a.cpp
#include <iostream>
#include <sstream>
#include <cstdint>
#include <list>
#include "test_function.h"
struct stSameNameButDifferent
{
uint32_t nPlayCode;
uint32_t nGameID;
std::string sGameName;
};
void test_a()
{
std::list<stSameNameButDifferent> lstSt;
for(int i=0; i<10; ++i)
{
stSameNameButDifferent st;
st.nPlayCode = i;
st.nGameID = 100+i;
std::ostringstream osBuf;
osBuf << "Game_" << i;
st.sGameName = osBuf.str();
lstSt.push_back(st);
}
for(auto &st : lstSt)
{
std::cout << st.nPlayCode << ", " << st.nGameID << ", " << st.sGameName << std::endl;
}
}
test_b.cpp
#include <iostream>
#include <sstream>
#include <cstdint>
#include <list>
#include "test_function.h"
struct stSameNameButDifferent
{
uint32_t nPlayCode;
uint32_t nGameID;
float fDiscountRate;
std::string sGameName;
};
void test_b()
{
std::list<stSameNameButDifferent> lstSt;
for(int i=0; i<10; ++i)
{
stSameNameButDifferent st;
st.nPlayCode = i;
st.nGameID = 1000+i;
st.fDiscountRate = (float)i/100;
std::ostringstream osBuf;
osBuf << "Game_" << i;
st.sGameName = osBuf.str();
lstSt.push_back(st);
}
for(auto &st : lstSt)
{
std::cout << st.nPlayCode << ", " << st.nGameID << ", " << st.sGameName << std::endl;
}
}
To avoid clashes of the same struct names in multiple translation units, you have to put them in an unnamed namespace like so:
namespace {
struct stSameNameButDifferent {
uint32_t nPlayCode;
uint32_t nGameID;
std::string sGameName;
};
}
This will make stSameNameButDifferent only seen privately in the corresponding translation unit (.cpp file).
Otherwise the linker will resolve the symbol with the first one found, hence the errors you see at runtime.
you have defined stSameNameButDifferent in global scope, so compiler cannot see and analyze both definitions to same struct and it only take the first one it meet and that's why you are getting an error.
You can use two different namespaces for test_a and test_b, so you will not get any error.

viennacl with complex numbers

I'm using viennacl to solve a linear system of equations (AX = B) with the graphic card. Also, the code uses armadillo.
My system of equations have complex numbers. So the question is: Can I solve a system of equations (with complex numbers) using viennacl?
Above is an example of a working code with real numbers.
// System headers
#include <iostream>
// Armadillo headers (disable BLAS and LAPACK to avoid linking issues)
#define ARMA_DONT_USE_BLAS
#define ARMA_DONT_USE_LAPACK
#include <armadillo>
#include <complex>
#define VIENNACL_WITH_ARMADILLO 1
// ViennaCL headers
#include "viennacl/linalg/cg.hpp"
#include "viennacl/linalg/bicgstab.hpp"
#include "viennacl/linalg/gmres.hpp"
#include "viennacl/io/matrix_market.hpp"
#include "vector-io.hpp"
//using namespace arma;
using namespace viennacl::linalg;
using namespace std;
typedef arma::mat armat;
typedef arma::vec arvec;
typedef complex<double> dcmplx;
int main(void)
{
int N = 500;
armat A(N,N);
A.randu();
arvec B(N);
B.randu();
arvec X(N);
arvec residual(N);
viennacl::matrix<double> vcl_A(N, N);
viennacl::vector<double> vcl_B(N);
viennacl::vector<double> vcl_X(N);
viennacl::vector<double> vcl_result(N);
viennacl::copy(A, vcl_A);
viennacl::copy(B, vcl_B);
viennacl::copy(X, vcl_X);
std::cout << "----- Running GMRES -----" << std::endl;
vcl_X = viennacl::linalg::solve(vcl_A, vcl_B, viennacl::linalg::gmres_tag());
viennacl::copy(vcl_A, A);
viennacl::copy(vcl_B, B);
viennacl::copy(vcl_X, X);
residual = A * X - B;
cout << "Relative residual: " << norm(residual) / norm(B) << endl;
}
Complex version of the code:
#include <iostream>
// Armadillo headers (disable BLAS and LAPACK to avoid linking issues)
#define ARMA_DONT_USE_BLAS
#define ARMA_DONT_USE_LAPACK
#include <armadillo>
#include <complex>
#define VIENNACL_WITH_ARMADILLO 1
// ViennaCL headers
#include "viennacl/linalg/cg.hpp"
#include "viennacl/linalg/bicgstab.hpp"
#include "viennacl/linalg/gmres.hpp"
#include "viennacl/io/matrix_market.hpp"
#include "vector-io.hpp"
//using namespace arma;
using namespace viennacl::linalg;
using namespace std;
typedef arma::cx_mat armat;
typedef arma::cx_vec arvec;
typedef complex<double> dcmplx;
int main(void)
{
int N = 500;
armat A(N,N);
A.randu();
arvec B(N);
B.randu();
arvec X(N);
arvec residual(N);
viennacl::matrix<dcmplx> vcl_A(N, N);
viennacl::vector<dcmplx> vcl_B(N);
viennacl::vector<dcmplx> vcl_X(N);
viennacl::vector<dcmplx> vcl_result(N);
viennacl::copy(A, vcl_A);
viennacl::copy(B, vcl_B);
viennacl::copy(X, vcl_X);
std::cout << "----- Running GMRES -----" << std::endl;
vcl_X = viennacl::linalg::solve(vcl_A, vcl_B, viennacl::linalg::gmres_tag());
viennacl::copy(vcl_A, A);
viennacl::copy(vcl_B, B);
viennacl::copy(vcl_X, X);
residual = A * X - B;
cout << "Relative residual: " << norm(residual) / norm(B) << endl;
std::cout << "----- Running BiCGStab -----" << std::endl;
vcl_X = viennacl::linalg::solve(vcl_A, vcl_B, viennacl::linalg::bicgstab_tag());
viennacl::copy(vcl_A, A);
viennacl::copy(vcl_B, B);
viennacl::copy(vcl_X, X);
residual = A * X - B;
cout << "Relative residual: " << norm(residual) / norm(B) << endl;
std::cout << "----- Running CG -----" << std::endl;
vcl_X = viennacl::linalg::solve(vcl_A, vcl_B, viennacl::linalg::cg_tag());
viennacl::copy(vcl_A, A);
viennacl::copy(vcl_B, B);
viennacl::copy(vcl_X, X);
residual = A * X - B;
cout << "Relative residual: " << norm(residual) / norm(B) << endl;
}
ViennaCL currently does not support complex numbers. The primary technical reason is that OpenCL does not natively provide support for complex numbers. While emulating complex arithmetic via real arithmetic is certainly possible, we were reluctant to go down this path and (wrongly?) hoped that a standardization for complex will come soon.

Multiple Definitions in C++ (Visual Basic 2010)

I'm attempting to practice some coding in my free time (combining a number of different interests of mine to help keep myself engaged) and I've encountered a odd error that I can't find the answer to. I have 4 files that I'm working with, two header files, one class definition file and a main file. I'm fairly confident I'm not including the Dice.h file more then once (however that is where the error points to and I'm not sure anymore, hence this question). What have I bungled here to produce these errors?
The error codes
Error 3 error LNK1169: one or more multiply defined symbols found (file path trimmed)
Error 2 error LNK2005: "int __cdecl dice(int,int)" (?dice##YAHHH#Z) already defined in Creature.obj (file path trimmed)
The filepath: c:\Users\Username\documents\visual studio2010\Projects\RPGTest\RPGTest\RPGTest.(error 3 referenced a .exe file, error 2 referenced a .obj file).
The code itself:
Dice.h
#ifndef SET_DICE_H_
#define SET_DICE_H_
#include <iomanip>
#include <iostream>
#include <stdlib.h>
using namespace std;
int dice(int number, int sides){
int total=0, dice;
srand(time(NULL));
int results=0;
do {
dice = rand()%sides+1;
total+=dice;
number--;
} while (number > 0);
results = total;
return results;
}
#endif
Creature.h
#ifndef CREATURE_H_
#define CREATURE_H_
#include <iomanip>
#include <iostream>
#include "Dice.h"
using namespace std;
class Creature {
public:
Creature(int,int,int,int,int,int,int,int,int,int,int,int);
void set_hp();
void set_saves();
void set_ac();
void set_bab();
void set_name();
void update_hp(int);
void update_ac(int);
void update_fsave(int);
void update_rsave(int);
void update_wsave(int);
int get_ac();
int get_hp();
int get_fsave();
int get_rsave();
int get_wsave();
int get_bonus(int);
int get_bab();
string get_name();
private:
int strength, dexterity, constitution, intellegence, wisdom, charisma;
int bab, fbsave, rbsave, wbsave;
int hdnum, hdsize;
int hp, fsave, rsave, wsave, ac;
string name;
};
#endif
Creature.cpp
#include "Creature.h"
#include <math.h>
#include <iostream>
using namespace std;
Creature::Creature(int strength,int dexterity,int constitution,
int intellegence,int wisdom,int charisma,int bab,int fbsave,
int rbsave,int wbsave,int hdnum,int hdsize){
strength = strength;
dexterity = dexterity;
constitution = constitution;
intellegence = intellegence;
wisdom = wisdom;
charisma = charisma;
bab = bab;
fbsave = fbsave;
rbsave = rbsave;
wbsave = wbsave;
hdnum = hdnum;
hdsize = hdsize;
}
int Creature::get_bonus(int stat){
int bonus = floor((double(stat)-10)/2);
return bonus;
}
void Creature::set_ac(){
ac=10+get_bonus(dexterity);
}
void Creature::set_hp(){
hp = dice(hdnum,hdsize) + get_bonus(constitution)*hdnum;
}
void Creature::set_saves(){
fsave = fbsave + get_bonus(constitution);
rsave = rbsave + get_bonus(dexterity);
wsave = wbsave + get_bonus(wisdom);
}
void Creature::set_bab(){
bab = hdnum;
}
void Creature::set_name(){
cout << "Please enter a name for this creature: ";
cout << "\nSorry! I don't work yet!";
cout << "\nInstead all creatures are named Larry!\n";
name = "Larry!";
}
void Creature::update_hp(int input){
hp = hp + input;
}
void Creature::update_fsave(int input){
fsave = fsave+input;
}
void Creature::update_rsave(int input){
rsave = rsave+input;
}
void Creature::update_wsave(int input){
wsave = wsave+input;
}
void Creature::update_ac(int input){
ac = ac+input;
}
int Creature::get_ac(){
return ac;
}
int Creature::get_hp(){
return hp;
}
int Creature::get_fsave(){
return fsave;
}
int Creature::get_rsave(){
return rsave;
}
int Creature::get_wsave(){
return wsave;
}
int Creature::get_bab(){
return bab;
}
RPGTest.cpp
#include "Creature.h"
#include <math.h>
//#include "Dice.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int str = dice(3,6), dex = dice(3,6), con = dice(3,6), intel = dice(3,6), wis = dice(3,6), cha = dice(3,6);
int fbs = dice(1,6), rbs = dice(1,6), wbs = dice(1,6);
int hdn = dice(1,10), hds = 8, bab = dice(1,8);
cout << "Welcome to RPG Creature Tester v0.1\n";
cout << "This .exe file is meant to test the creature class functions and definitions.\n";
cout << "This will be done by randomly generating and displaying a creature.\n";
cout << "What you don't see right now is the random generation of a creature.\n";
cout << "Once it's finished, the \'statsheet\' will be shown.\n";
cout << "Cheers!\n\n";
Creature potato (str, dex, con, intel, wis, cha, bab, fbs, rbs, wbs, hdn, hds);
potato.set_ac();
potato.set_hp();
potato.set_name();
potato.set_saves();
cout << "OUTPUT BRICK YAY\n";
cout << "Str: " << str << endl;
cout << "HP: " << potato.get_hp() << " AC: " << potato.get_ac() << " Fort/Reflex/Will Save: " << potato.get_fsave() << "/" << potato.get_rsave() << "/" << potato.get_wsave();
return 0;
}
Since I'm mainly self-taught I'm happy for any other advice but my main issue is that I'm not sure why I'm getting the "multiple" definition error. I did some research into other questions with similar error messages but I didn't see anything that immediately jumped out at me as "the answer".
Thanks all!
C++ works by compiling single translation units and then linking them together.
This means that each source file gets compiled on its own. Since the #include directive basically inserts all the code included, in your situation you end up having multiple translation units which define
int dice(int number, int sides) {
...
}
Compilation goes through fine but, when linking, multiple definition of this function are found so this generates the error.
To solve this problem you have two ways:
declare int dice(int, int) in a header file but define (implement it) in a source file
keep the definition as it is but prepend static to it. This tells the compiler that each translation unit will get its own dice method. This solution, although tempting, leads to binary size increase since you will have multiple implementation of the same method

what is the exact time to run a program?

I want the exact time to run a program, I use it from clock(). But there is a problem that I can not give an exact time for small n like 2000.
I want it to return the correct answer for n=1000.
#include <iostream>
#include <ctime>
#include <algorithm>
using namespace std;
#define show_time(x, y) cout << endl << #x << " : " << y << endl;
int main()
{
int n;
cin >> n;
int *a = new int[n];
for(int i=0; i<n; i++)
a[i] = i;
random_shuffle(a, a+n);
int last = clock();
//STL_sort:
sort(a, a+n);
int lastP = clock();
show_time(STL_sort, (double)(lastP-last)/CLOCKS_PER_SEC);
return 0;
}
The output is 0. (Definitely 0 will not be the answer)
What platform are you running on? If you're on Windows, you could try the high-resolution time library.
If you have access to C++11, there is a header called chrono that has similar functionality, and is portable (ish)!