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.
Try wrapping your header like this:
extern "C"
{
#include "stdafx.h"
#include "iDEMA.h"
}
If VS complains about the extern keyword go to Project Properties > C/C++ > Advanced > Compile As and check Compile as C++.
For the Updated answer, it looks like your compiler is seeing two definitions of the same symbol.
Try using
#include <stdafx.h>
#include <iDEMA.h>
They look in different places. If it doesn't help, try the extern "C" with your old project (before update 10/10/15).
Maybe you've added some dll or lib to your PATH in your first try and after the "Update 10/10/15", you don't need them anymore.
Also read this
answer
and this
MSDN Building Visual C++ page.
Edit:
If possible, create a new project. Maybe, in your attempts, you've messed something.
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;
}
Related
I have two projects in my Solution (Visual Studio)
I want to assign the function
void _OnCycle()
{
printf("Success\n");
}
in the Dll( main.cpp ) to the pointer member function OnCycle of the structure PluginCallbacks.
extern "C" unsigned int PluginInit(PluginFuncs * pluginFuncs, PluginCallbacks * pluginCalls, PluginInfo * pluginInfo) {
pluginCalls->OnCycle = _OnCycle;
return 1;
}
But program is crashing. Entire code below.
//Project: ConsoleApplication1
//file: Dll1/ConsoleApplication1/ConsoleApplication1.cpp
#include <iostream>
#include "plugin.h"
#include <windows.h>
typedef unsigned int (__stdcall *PluginInit)(PluginFuncs* pluginFuncs, PluginCallbacks* pluginCalls, PluginInfo* pluginInfo);
int main()
{
std::cout << "Loading first dll\n";
HINSTANCE hGetProcIDDLL = LoadLibrary("../Release/Dll1.dll");
if (!hGetProcIDDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
// resolve function address here
PluginInit funci = (PluginInit)GetProcAddress(hGetProcIDDLL, "PluginInit");
if (!funci) {
std::cout << "could not locate the function" << std::endl;
return EXIT_FAILURE;
}
PluginFuncs a;
PluginCallbacks b;
PluginInfo c;
std::cout << "PluginInit(a,b,c) returned " << funci(&a,&b, &c) << "\n";
std::cout << "Now going to call OnCycle\n";
b.OnCycle();
std::cout << "Done";
return EXIT_SUCCESS;
}
//Project: ConsoleApplication1
//file: Dll1/ConsoleApplication1/plugin.h
#pragma once
#include <stdint.h>
## Heading ##
typedef struct _Settings {
uint32_t structSize;
uint32_t flags;
} Settings;
typedef struct _PluginInfo {
uint32_t structSize;
char name[32];
} PluginInfo;
typedef struct _PluginFuncs {
uint32_t structSize;
uint32_t(*GetVersion) (void);
}PluginFuncs;
typedef struct {
uint32_t structSize;
void (*OnCycle) ();
}PluginCallbacks;
and second project
//Project: Dll1
//file: Dll1/Dll1/main.cpp
#include "plugin.h"
#include "main.h"
#include "stdio.h"
void _OnCycle() {
printf("Success\n");
}
extern "C" unsigned int PluginInit(PluginFuncs * pluginFuncs, PluginCallbacks * pluginCalls, PluginInfo * pluginInfo) {
printf("PluginInit called\n");
pluginCalls->OnCycle = _OnCycle;
return 1;
}
//Project: Dll1
//file: Dll1/Dll1/main.h
#define EXPORT __declspec(dllexport)
#include "plugin.h"
#ifdef __cplusplus
extern "C" {
#endif
EXPORT unsigned int PluginInit(PluginFuncs* pluginFuncs, PluginCallbacks* pluginCalls, PluginInfo* pluginInfo);
#ifdef __cplusplus
}
#endif
//Project: Dll1
//file: Dll1/Dll1/plugin.h
#pragma once
#include <stdint.h>
typedef struct _Settings {
uint32_t structSize;
uint32_t flags;
} Settings;
typedef struct _PluginInfo {
uint32_t structSize;
char name[32];
} PluginInfo;
typedef struct _PluginFuncs {
uint32_t structSize;
uint32_t(*GetVersion) (void);
}PluginFuncs;
typedef struct {
uint32_t structSize;
void (*OnCycle) ();
}PluginCallbacks;
It builds but crashes on execution.
//Output
C:\Users\[hidden]\source\repos\Dll1\Release>ConsoleAPplication1
Loading first dll
PluginInit called
PluginInit(a,b,c) returned 1
Now going to call OnCycle
C:\Users\[hidden]\source\repos\Dll1\Release>
See, it crashes as 'Done' message not printed.
How this is to be done correctly.?
It seems my problem is solved by creating a pointer, malloc'ing it and passing it to dll.
Here is the piece of code
PluginFuncs* a = NULL;
PluginCallbacks* b = NULL;
PluginInfo* c = NULL;
a = (PluginFuncs*)malloc(sizeof(PluginFuncs));
b = (PluginCallbacks*)malloc(sizeof(PluginCallbacks));
c= (PluginInfo*)malloc(sizeof(PluginInfo));
std::cout << "PluginInit(a,b,c) returned " << funci(a,b, c) << "\n";
std::cout << "Now going to call OnCycle\n";
if (b && b->OnCycle)
b->OnCycle();
std::cout << "Done";
and output
Loading first dll
PluginInit(a,b,c) returned 1
Now going to call OnCycle
Success
Done
Thanks
I need to import the dll function into my project and use it.
However, when importing it into my project with GetProcAddress() function it does not seem to work. Function returns null and the simple if check finishes the program.
I'm pretty sure there is some problem with my code, but I don't seem to be able to find it. Here is the code of Library.h file
#pragma once
#include <iostream>
#include <windows.h>
#include <string>
#include <cmath>
using namespace std;
#ifdef MY_DLL_EXPORTS
#define MY_DLL_API extern "C" _declspec(dllexport)
#else
#define MY_DLL_API extern "C" _declspec(dllimport)
#endif
struct args
{
int Elements;
int sum;
int* Array;
};
DWORD WINAPI NoSynchroSum(LPVOID);
void Monitoring(int);
Library.cpp file
#include "pch.h"
#include "framework.h"
#include "Library.h"
using namespace std;
DWORD WINAPI NoSynchroSum(LPVOID arg)
{
args* _args = (args*)arg;
for (int i = 0; i < _args->Elements; i++)
{
_args->sum += _args->Array[i];
}
return 0;
}
void Monitoring(int Elements)
{
int ElementsAmount = Elements;
HANDLE handle;
int suspendCount = 1;
int sum = 0;
srand(time(0));
int* Array = new int[ElementsAmount];
for (int i = 0; i < ElementsAmount; i++)
{
Array[i] = rand() % 21 - 10;
}
args* _args = new args;
_args->Elements = ElementsAmount;
_args->sum = sum;
_args->Array = Array;
handle = CreateThread(NULL, 0, NoSynchroSum, (LPVOID)_args, NULL, NULL);
cout << "Counted Sum = " << sum << endl;
CloseHandle(handle);
delete[] Array;
delete _args;
}
And my other project code, where i'm trying to import and use the function
#include <iostream>
#include <Windows.h>
using namespace std;
int main() {
HINSTANCE hInstance = LoadLibrary(L"D:\\Visual Studio 2022\\repos\\LabOS_7_DLL\\x64\\Debug\\DLLibrary.dll");
if (!hInstance) {
std::cout << "Library not loaded.\n";
return 1;
}
void (*pMainFunc)(int);
pMainFunc = (void(*)(int))GetProcAddress(hInstance, "Monitoring"); // експорт функції створення потоку
if (!pMainFunc)
{
std::cout << "Function not loaded.\n";
return 1;
}
int ElementsAmount = 0;
while (true)
{
cout << "enter size of array: ";
cin >> ElementsAmount;
if (ElementsAmount < 100)
{
cout << "size of array must be >=100\n";
continue;
}
break;
}
pMainFunc(ElementsAmount);
FreeLibrary(hInstance);
return 0;
}
I test the code and get the GetLastError:127 ERROR_PROC_NOT_FOUND:The specified procedure could not be found.
It means that there is no exported function with that name.
I suggest you should use the following code in the Library.h:
MY_DLL_API DWORD WINAPI NoSynchroSum(LPVOID);
MY_DLL_API void Monitoring(int);
I try to set up a test project in Visual Studio 2019.
The module that I want to test is written in c.
I'm using the native VS cpp Testframework.
I can compile and run my program but not my unittest. Once I try to run that one I get the following error:
Fehler LNK2019 Verweis auf nicht aufgelöstes externes Symbol "_is_prime" in Funktion ""public: void __thiscall UnitTest1::UnitTest1::TestMethod1(void)" (?TestMethod1#UnitTest1#1#QAEXXZ)". UnitTest1 C:\Users\Alexander Leibenath\Documents\20210210_Prime_VS\Primzahlprüfer\Primzahlprüfer\UnitTest1\UnitTest1.obj 1
What I've tried so far:
told the comiler in the header file that if he is a cpp compiler he should interpret the c-functions as c
Here is my code:
/* File calc.c ----------------------------------------------- */
/* Tell if the argument is a prime (ret 1) or not (ret 0) */
int is_prime(unsigned val)
{
unsigned divisor;
if (val == 1 || val == 2 || val == 3)
return 1;
if (val % 2 == 0)
return 0;
for (divisor = 3; divisor < val / 2; divisor += 2)
{
if (val % divisor == 0)
return 0;
}
return 1;
}
my calc.h
/* File calc.h ----------------------------------------------- */
/* Tell if the argument is a prime (ret 0) or not (ret 1) */
#ifdef __cplusplus
extern "C" {
#endif
//C code goes here
int is_prime(unsigned val);
#ifdef __cplusplus
} // extern "C"
#endif
and my unittest cpp file:
#include "pch.h"
#include "CppUnitTest.h"
#include "../Primzahlprüfer/calc.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace UnitTest1
{
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod1)
{
int result;
result = is_prime(5);
}
};
}
I'm thankful for all the help I can get. Thanks
After I tested the code, I found that it has nothing to do with the C file.
First of all, you need to check if you have added ..\calc\Debug\*.obj in Properties->Linker->Input->Additional Dependencies.
Then, you could add the reference to the calc in References.
When I build main.cpp get error: undefined reference to WinMain#16, use Code::Blocks created dll project in codeblocks
When I build main.cpp get error: undefined reference to WinMain#16, use Code::Blocks created dll project in codeblocks
When I build main.cpp get error: undefined reference to WinMain#16, use Code::Blocks created dll project in codeblocks
When I build main.cpp get error: undefined reference to WinMain#16, use Code::Blocks created dll project in codeblocks
main.cpp (created by code:blocks)
#include "main.h"
#include <string>
#include <fstream>
#include <windows.h>
#include <iostream>
#include <io.h>
using namespace::std;
void DLL_EXPORT createFiles(int filesAmount){
int n=5;
int a[5] = {1, 23, 47, 45, 21};
for(int i=0; i<filesAmount; i++){
string s1 = "files\\";
string s2 = to_string(i+1);
string s3 = s1 + s2 + ".txt";
ofstream fout(s3);
fout << "0";
fout.close();
}
for (int i=0; i<n; i++){
string s1 = "files\\";
string s2 = to_string(a[i]);
string s3 = s1 + s2 + ".txt";
ofstream fout (s3);
fout << "1";
fout.close();
}
}
DWORD WINAPI DLL_EXPORT lookForFile(void *data, HANDLE hSem){
Pair *pairs = (Pair *) data;
int start = (pairs->start);
int finish = (pairs->finish);
char a;
DWORD dwWaitResult = WaitForSingleObject( hSem, 1);
while(dwWaitResult!=WAIT_OBJECT_0)
{
cout << pairs->threadNumber << " thread waiting for semaphore..."
<<endl;
dwWaitResult = WaitForSingleObject( hSem, 1);
}
cout << pairs->threadNumber << " thread has been runned"<<endl;
Sleep(100);
for(int i=start; i<=finish; i++){
string s1 = "files\\";
string s2 = to_string(i+1);
string s3 = s1 + s2 + ".txt";
ifstream F(s3);
a = F.get();
if(a == '1')
cout << "\"1\" was found by " << (pairs->threadNumber) << " thread
in " << s2 <<".txt"<<endl;
F.close();
}
ReleaseSemaphore( hSem, 1, NULL );
cout << pairs->threadNumber << " thread has been finished"<<endl;
return 0;
}
void DLL_EXPORT makeCounts(int filesAmount, int numberOfThreads, Pair
pairs[]){
int fp = filesAmount/numberOfThreads-1;
int st = 0;
for(int i = 0; i < numberOfThreads; i++){
if(i == numberOfThreads-1){
pairs[i].start = st;
pairs[i].finish = filesAmount-1;
}
else{
pairs[i].start = st;
pairs[i].finish = st+fp;
st+=fp+1;
}
}
}
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD
fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// attach to process
// return FALSE to fail DLL load
break;
case DLL_PROCESS_DETACH:
// detach from process
break;
case DLL_THREAD_ATTACH:
// attach to thread
break;
case DLL_THREAD_DETACH:
// detach from thread
break;
}
return TRUE; // succesful
}
main.h (created by code:blocks)
#ifndef __MAIN_H__
#define __MAIN_H__
struct Pair {
int start;
int finish;
int threadNumber;
};
#include <windows.h>
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
void DLL_EXPORT createFiles(int filesAmount);
DWORD WINAPI DLL_EXPORT lookForFile(void *data, HANDLE hSem);
void DLL_EXPORT makeCounts(int filesAmount, int numberOfThreads, Pair
pairs[]);
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
I'm encountering the following linker issue when I try to build my project.
I've had a look through the other posts here and as far as I can see, the only externals I'm using are members of standard (and identified with std::), or primitives. Is there something obvious that I'm missing here?
Building using Eclipse C++ (Mars) on Win 7 professional 64bit using the internal eclipse builder.
Log:
link /debug /nologo /OUT:SAD-Snoop.exe "src\ByteScanner.obj" "src\EncType.obj" "src\SAD-Snoop.obj" "src\SearchHits.obj"
SearchHits.obj : error LNK2019: unresolved external symbol "public: long __thiscall SearchHits::GetHitAddress(unsigned int)" (GetHitAddress#SearchHits##QAEJI#Z) referenced in function "public: bool __thiscall SearchHits::Merge(class SearchHits)" (?Merge#SearchHits##QAE_NV1##Z)
SAD-Snoop.exe : fatal error LNK1120: 1 unresolved externals
14:28:44 Build Finished (took 909ms)
Header:
/*
* SearchHits.h
*
* Created on: 30 Jun 2015
* Author: Nick Boyd
*/
#ifndef SEARCHHITS_H_
#define SEARCHHITS_H_
#include <iostream>
#include <string>
#include <vector>
class SearchHits {
public:
SearchHits();
~SearchHits();
bool AddHit(std::string content, long address);
unsigned int CountHits();
std::string GetHit(unsigned int hitNumber);
long GetHitAddress(unsigned int hitNumber);
bool Merge(SearchHits hits);
private:
std::vector<std::string> hits;
std::vector<long> hitAddresses;
};
#endif /* SEARCHHITS_H_ */
class:
/*
* SearchHits.cpp
*
* Created on: 30 Jun 2015
* Author: Nick Boyd
*/
#include "SearchHits.h"
#include <string>
#include <iostream>
#include <vector>
std::vector<std::string> hitContents;
std::vector<long> hitAddresses;
SearchHits::SearchHits() {
}
SearchHits::~SearchHits() {
hitContents.clear();
hitAddresses.clear();
}
bool SearchHits::AddHit(std::string hitContent, long address) {
hitContents.push_back(hitContent);
hitAddresses.push_back(address);
return ((hitContents.back() == hitContent)
&& (hitAddresses.back() == address));
}
unsigned int SearchHits::CountHits() {
return hitContents.size();
}
std::string SearchHits::GetHit(unsigned int hitNumber) {
if (hitNumber < hitContents.size()) {
return hitContents[hitNumber];
} else {
std::cout << "Error in Function [SearchHits::GetHit()]" << std::endl
<< "Parameter [hitNumber] out of bounds: "
<< hitNumber + " Upper Limit: " << hitContents.size()
<< std::endl;
throw new std::invalid_argument(
"Error in Function [SearchHits::GetHit()] Parameter [hitNumber] out of bounds: "
+ std::to_string(hitNumber));
}
}
long GetHitAddress(unsigned int hitNumber) {
if (hitNumber < hitContents.size()) {
return hitAddresses[hitNumber];
} else {
std::cout << "Error in Function [SearchHits::GetHitAddress()]"
<< std::endl << "Parameter [hitNumber] out of bounds: "
<< hitNumber << " Upper Limit: " << hitContents.size()
<< std::endl;
throw new std::invalid_argument(
"Error in Function [SearchHits::GetHitAddress()] Parameter [hitNumber] out of bounds: "
+ std::to_string(hitNumber));
}
}
bool SearchHits::Merge(SearchHits hits) {
bool overallResult = true;
unsigned int i = 0;
while ((i < hits.CountHits()) && overallResult) {
bool tempResult = false;
unsigned char attemptNum = 1;
while ((tempResult == false) && (attemptNum++ <= 5)) {
tempResult = this->AddHit(hits.GetHit(i),hits.GetHitAddress(i));
}
overallResult = (overallResult && tempResult);
++i;
}
if (overallResult) {
hits.~SearchHits();
}
return overallResult;
}
Change
long GetHitAddress(unsigned int hitNumber)
to
long SearchHits::GetHitAddress(unsigned int hitNumber)