This is my second attempt at a C++ program so I'm still learning.
I'm trying to create a DLL to work with Metatrader 4 which uses the ta-lib technical analysis library using Visual Studio 2013 Community.
However, when I build the solution I get the following linker errors and I don't know how to fix them.
Error 4 error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) already defined in libcmt.lib(typinfo.obj) C:\Users\Documents\Visual Studio 2013\Projects\iDEMA\iDEMA\MSVCRT.lib(ti_inst.obj) iDEMA
Error 5 error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) already defined in libcmt.lib(typinfo.obj) C:\Users\Documents\Visual Studio 2013\Projects\iDEMA\iDEMA\MSVCRT.lib(ti_inst.obj) iDEMA
Error 2 error LNK2005: _free already defined in libcmt.lib(free.obj) C:\Users\Documents\Visual Studio 2013\Projects\iDEMA\iDEMA\MSVCRT.lib(MSVCR120.dll) iDEMA
Error 3 error LNK2005: _malloc already defined in libcmt.lib(malloc.obj) C:\Users\Documents\Visual Studio 2013\Projects\iDEMA\iDEMA\MSVCRT.lib(MSVCR120.dll) iDEMA
Warning 1 warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library C:\Users\Documents\Visual Studio 2013\Projects\iDEMA\iDEMA\LINK iDEMA
Error 7 error LNK1169: one or more multiply defined symbols found C:\Users\Documents\Visual Studio 2013\Projects\iDEMA\Release\iDEMA.dll iDEMA
Error 6 error LNK2005: _DllMain@12 already defined in uafxcw.lib(dllmodul.obj) C:\Users\Documents\Visual Studio 2013\Projects\iDEMA\iDEMA\* CIL library *(* CIL module *) iDEMA
My header file is this
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the IDEMA_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// IDEMA_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef IDEMA_EXPORTS
#define IDEMA_API __declspec(dllexport)
#else
#define IDEMA_API __declspec(dllimport)
#endif
#pragma pack(push,1)
struct RateInfo
{
__int64 ctm;
double open;
double low;
double high;
double close;
unsigned __int64 vol_tick;
int spread;
unsigned __int64 vol_real;
};
#pragma pack(pop)
enum ENUM_PRICE
{
PRICE_OPEN,
PRICE_LOW,
PRICE_HIGH,
PRICE_CLOSE
};
// This class is exported from the iDEMA.dll
class IDEMA_API CiDEMA {
public:
CiDEMA(void);
double iDEMA(RateInfo, int, int, int, ENUM_PRICE);
};
extern IDEMA_API int niDEMA;
IDEMA_API int fniDEMA(void);
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string>
#include "C:\ta-lib-0.4.0-msvc\ta-lib\c\include\ta_libc.h"
#pragma once
#ifndef __AFXWIN_H__
#error "include 'stdafx.h' before including this file for PCH"
#endif
#include "resource.h" // main symbols
And my code is this
// iDEMA.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "iDEMA.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define WIN32_LEAN_AND_MEAN
#define MT4_EXPFUNC __declspec(dllexport)
using namespace std;
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
//---
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
//---
return(TRUE);
}
MT4_EXPFUNC double __stdcall iDEMA(const RateInfo* rates, const int rates_total, const int period, const int shift, const ENUM_PRICE applied_price)
{
//---
if (rates == NULL)
{
printf("iDEMA: NULL array\n");
return(0.0);
}
//---
if (rates_total<0 || rates_total<2 * period)
{
printf("iDEMA: wrong rates_total number (%d)\n", rates_total);
return(0.0);
}
//---
if (period<2 || period>100000)
{
printf("iDEMA: wrong period number (%d)\n", period);
return(0.0);
}
//---
if (shift<0 || shift >= rates_total)
{
printf("iDEMA: wrong shift number (%d)\n", shift);
return(0.0);
}
//---
if (applied_price<0 || applied_price>3)
{
printf("iDEMA: wrong applied price (%d)\n", applied_price);
return(0.0);
}
//---
TA_RetCode retCode;
retCode = TA_Initialize();
if (retCode != TA_SUCCESS)
{
printf("TA_LIB initialistion failed (%d)!\n", retCode);
return(0.0);
}
vector<TA_Real> dataArray;
const TA_Real* dataArray_c_pointer = dataArray.data();
// DEMA = ( 2 * EMA(n)) - (EMA(EMA(n)) ), where n= period
for (int nitem = rates_total - 1 - shift - (2 * period); nitem < rates_total - 1 - shift; nitem++)
{
TA_Real value = 0.0;
switch (applied_price)
{
case PRICE_OPEN: value = rates[nitem].open; break;
case PRICE_LOW: value = rates[nitem].low; break;
case PRICE_HIGH: value = rates[nitem].high; break;
case PRICE_CLOSE: value = rates[nitem].close; break;
}
dataArray[nitem] = value;
}
TA_Integer outBegin = 0, outElements = 0;
int beginIndx, endIndx;
beginIndx = endIndx = dataArray.size() - 1;
int array_size = endIndx - beginIndx + 1;
cout << "beginIndx = " << to_string(beginIndx) << endl << "endIndx = " << to_string(endIndx) << endl << "array_size = " << to_string(array_size) << endl;
vector<TA_Real> outDema(array_size, 0.0);
TA_Real* outDema_c_pointer = outDema.data();
retCode = TA_DEMA(beginIndx, endIndx, dataArray_c_pointer, period, &outBegin, &outElements, outDema_c_pointer);
double value = 0.0;
if (retCode == TA_SUCCESS)
{
cout << "outBegin = " << outBegin << " outElements = " << outElements << endl;
int lastElement = outElements - 1;;
cout << "outDema.at(" << to_string(lastElement) << ") = " << to_string(outDema.at(lastElement)) << endl;
delete dataArray_c_pointer;
delete outDema_c_pointer;
value = outDema.at(lastElement);
}
retCode = TA_Shutdown();
return value;
}
I installed the library using nuGet.
Could you help to compile this DLL please.
Thanks in advance.
Update 10/10/15
I removed the package nuGet and used static linking from a different directory.
I'm now getting these linker errors:
Error 2 error LNK1169: one or more multiply defined symbols found C:\Users\Documents\Visual Studio 2013\Projects\iDEMA\Release\iDEMA.dll iDEMA
Error 1 error LNK2005: _DllMain@12 already defined in mfcs120u.lib(dllmodul.obj) C:\Users\Documents\Visual Studio 2013\Projects\iDEMA\iDEMA\* CIL library *(* CIL module *) iDEMA
Still don't understand how to fix them!
Any help will be appreciated.
Thanks.
Managed to get it to link after modifying the header and source files. Here's the final result:
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the IDEMA_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// IDEMA_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#define WIN32_LEAN_AND_MEAN
#define MT4_EXPFUNC __declspec(dllexport)
#pragma pack(push,1)
struct RateInfo
{
__int64 ctm;
double open;
double low;
double high;
double close;
unsigned __int64 vol_tick;
int spread;
unsigned __int64 vol_real;
};
enum ENUM_PRICE
{
PRICE_OPEN,
PRICE_LOW,
PRICE_HIGH,
PRICE_CLOSE
};
#pragma pack(pop)
// This class is exported from the iDEMA.dll
class MT4_EXPFUNC CiDEMA {
public:
CiDEMA(void);
double iDEMA(RateInfo, int, int, int, ENUM_PRICE);
};
extern MT4_EXPFUNC int niDEMA;
MT4_EXPFUNC int fniDEMA(void);
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string>
#include "C:\ta-lib-0.4.0-msvc\ta-lib\c\include\ta_libc.h"
#pragma once
#ifndef __AFXWIN_H__
#error "include 'stdafx.h' before including this file for PCH"
#endif
#include "resource.h" // main symbols
And the source file:
// iDEMA.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "iDEMA.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
using namespace std;
MT4_EXPFUNC double __stdcall iDEMA(const RateInfo* rates, const int rates_total, const int period, const int shift, const ENUM_PRICE applied_price)
{
//---
if (rates == NULL)
{
printf("iDEMA: NULL array\n");
return(0.0);
}
//---
if (rates_total<0 || rates_total<2 * period)
{
printf("iDEMA: wrong rates_total number (%d)\n", rates_total);
return(0.0);
}
//---
if (period<2 || period>100000)
{
printf("iDEMA: wrong period number (%d)\n", period);
return(0.0);
}
//---
if (shift<0 || shift >= rates_total)
{
printf("iDEMA: wrong shift number (%d)\n", shift);
return(0.0);
}
//---
if (applied_price<0 || applied_price>3)
{
printf("iDEMA: wrong applied price (%d)\n", applied_price);
return(0.0);
}
//---
TA_RetCode retCode;
retCode = TA_Initialize();
if (retCode != TA_SUCCESS)
{
printf("TA_LIB initialistion failed (%d)!\n", retCode);
return(0.0);
}
vector<TA_Real> dataArray;
const TA_Real* dataArray_c_pointer = dataArray.data();
// DEMA = ( 2 * EMA(n)) - (EMA(EMA(n)) ), where n= period
for (int nitem = rates_total - 1 - shift - (2 * period); nitem < rates_total - 1 - shift; nitem++)
{
TA_Real value = 0.0;
switch (applied_price)
{
case PRICE_OPEN: value = rates[nitem].open; break;
case PRICE_LOW: value = rates[nitem].low; break;
case PRICE_HIGH: value = rates[nitem].high; break;
case PRICE_CLOSE: value = rates[nitem].close; break;
}
dataArray[nitem] = value;
}
TA_Integer outBegin = 0, outElements = 0;
int beginIndx, endIndx;
beginIndx = endIndx = dataArray.size() - 1;
int array_size = endIndx - beginIndx + 1;
cout << "beginIndx = " << to_string(beginIndx) << endl << "endIndx = " << to_string(endIndx) << endl << "array_size = " << to_string(array_size) << endl;
vector<TA_Real> outDema(array_size, 0.0);
TA_Real* outDema_c_pointer = outDema.data();
retCode = TA_DEMA(beginIndx, endIndx, dataArray_c_pointer, period, &outBegin, &outElements, outDema_c_pointer);
double value = 0.0;
if (retCode == TA_SUCCESS)
{
cout << "outBegin = " << outBegin << " outElements = " << outElements << endl;
int lastElement = outElements - 1;;
cout << "outDema.at(" << to_string(lastElement) << ") = " << to_string(outDema.at(lastElement)) << endl;
delete dataArray_c_pointer;
delete outDema_c_pointer;
value = outDema.at(lastElement);
}
retCode = TA_Shutdown();
return value;
}