GetProcAddress() does not load the function from the dll - c++

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);

Related

Using Dll to assign a function to the Pointer-Member-Function of a structure passed to it

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

How can i export a macro function and use it in a project .exe

I have a dll project (Server.dll) containing a Server.cpp
Server.cpp
#include "pch.h"
#include "Server.hpp"
extern "C" {
_declspec(dllexport) int Server::Add(int a, int b)
{
return a + b;
}
}
#define Function( Y ) \
\
extern "C" __declspec( dllexport)\
std::string Server::Y(std::string const& name) {\
return name; \
}\
I use these two functions in an other project client.exe
Here the main
#include <Windows.h>
#include <iostream>
typedef int(*pAdd) (int a, int b);
int main()
{
std::string path = "D:\\project\\Server.dll";
std::wstring stemp = std::wstring(path.begin(), path.end());
LPCWSTR sw = stemp.c_str();
HINSTANCE hinstance = LoadLibrary(sw);
if(!hinstance)
std::cout << "canot load library\n";
pAdd obj = (pAdd)GetProcAddress(hinstance, "Add");
if (obj) {
int result = obj(10, 20);
std::cout << "result = " << result << std::endl;
}
std::string func = "Client";
std::cout << "address = " << GetProcAddress(hinstance, "Y");
}
i can load Add function but i can't load Y function (address = 0000000000)
Any suggestions please ?
I want to post an example of the solution here maybe someone needs one day to create a macro function containing a function:
I have a dll project containing a class:
Here the code
#include "pch.h"
#include <iostream>
#define Function( Y ) \
\
extern "C" __declspec( dllexport)\
int Y(int a, int b) {\
return (a+b); \
}\
class TestMacro {
Function(Add);
};
In another exe project i loaded this function and use it here the code:
#include <Windows.h>
#include <iostream>
typedef int(*Y)(int a, int b);
int main()
{
std::string path = "D:\\project\\Server.dll";
std::wstring stemp = std::wstring(path.begin(), path.end());
LPCWSTR sw = stemp.c_str();
HINSTANCE hinstance = LoadLibrary(sw);
if(!hinstance)
std::cout << "canot load library\n";
std::cout << "address = " << GetProcAddress(hinstance, "Add")<< std::endl;
Y y = (Y)GetProcAddress(hinstance, "Add");
int result = y(2,3);
std::cout << "appel Y = " << result<< std::endl;
}
Here the ouput
address = 00007FFBF98C132F
appel Y = 5

Multiple Definitions Error of Global Arrays [duplicate]

This question already has answers here:
c++ multiple definitions of a variable
(5 answers)
multiple definition error c++
(2 answers)
What exactly is One Definition Rule in C++?
(1 answer)
Closed 2 years ago.
I am attempting to compile my c++ code, and I continue getting the error:
/tmp/ccEsZppG.o:(.bss+0x0): multiple definition of `mailboxes'
/tmp/ccEZq43v.o:(.bss+0x0): first defined here
/tmp/ccEsZppG.o:(.bss+0xc0): multiple definition of `threads'
/tmp/ccEZq43v.o:(.bss+0xc0): first defined here
/tmp/ccEsZppG.o:(.bss+0x120): multiple definition of `semaphores'
/tmp/ccEZq43v.o:(.bss+0x120): first defined here
collect2: error: ld returned 1 exit status
Here is my code:
addem.cpp
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include "mailbox.h"
using namespace std;
void *sumUp(void *arg);
int main(int argc, char *argv[]) {
int numThreads, minThreads, maxInt, minInt;
if (argc < 3) {
cout << "Error: Need three arguments" << endl;
return 1;
}
numThreads = atoi(argv[1]);
maxInt = atoi(argv[2]);
minThreads = 1;
minInt = 1;
if (numThreads < 1) {
cout << "Cannot work with less than one thread\n"
<< "It's okay but do better next time!\n"
<< "We'll work with 1 thread this time.\n";
numThreads = minThreads;
} else if (numThreads > MAXTHREAD) {
cout << "Sorry, the max for threads is 10.\n"
<< "We'll work with 10 threads this time.\n";
numThreads = MAXTHREAD;
}
if (maxInt < 1) {
cout << "What do you want me to do? I can't count backwards!\n"
<< "I can barely count forwards! Let's make the max number\n"
<< "be 1 to save time\n";
maxInt = minInt;
}
struct msg outgoingMail[numThreads];
int divider = maxInt / numThreads;
int count = 1;
//initialize arrays (mailboxes, semaphores)
for (int i = 0; i < numThreads; i++) {
sem_init(&semaphores[i], 0, 1);
outgoingMail[i].iSender = 0;
outgoingMail[i].type = RANGE;
outgoingMail[i].value1 = count;
count = count + divider;
if (i = numThreads - 1) {
outgoingMail[i].value2 = maxInt;
} else {
outgoingMail[i].value2 = count;
}
}
for (int message = 0; message < numThreads; message++) {
SendMsg(message+1, outgoingMail[message]);
}
int thread;
for (thread = 0; thread <= numThreads; thread++) {
pthread_create(&threads[thread], NULL, &sumUp, (void *)(intptr_t)(thread+1));
}
struct msg incomingMsg;
int total = 0;
for (thread = 0; thread < numThreads; thread++) {
RecvMsg(0, incomingMsg);
total = total + incomingMsg.value1;
}
cout << "The total for 1 to " << maxInt << " using "
<< numThreads << " threads is " << total << endl;
return 0;
}
void *sumUp(void *arg) {
int index,total;
index = (intptr_t)arg;
struct msg message;
RecvMsg(index, message);
message.iSender = index;
message.type = ALLDONE;
total = 0;
for (int i = message.value1; i <= message.value2; i++) {
total += i;
}
SendMsg(0, message);
return (void *) 0;
}
mailbox.cpp
#include <stdio.h>
#include <iostream>
#include "mailbox.h"
using namespace std;
int SendMsg(int iTo, struct msg &Msg) {
if (safeToCall(iTo)) {
cout << "Error calling SendMsg" << endl;
return 1;
}
sem_wait(&semaphores[iTo]);
mailboxes[iTo] = Msg;
sem_post(&semaphores[iTo]);
return 0;
}
int RecvMsg(int iFrom, struct msg &Msg) {
sem_wait(&semaphores[iFrom]);
if (safeToCall(iFrom)) {
cout << "Error calling RecvMsg" << endl;
return 1;
}
mailboxes[iFrom] = Msg;
sem_post(&semaphores[iFrom]);
return 0;
}
bool safeToCall(int location) {
bool safe = !(location < 0 || location > MAXTHREAD + 1);
return safe;
//return true;
}
mailbox.h
#ifndef MAILBOX_H_
#define MAILBOX_H_
#define RANGE 1
#define ALLDONE 2
#define MAXTHREAD 10
#include <semaphore.h>
#include <pthread.h>
struct msg {
int iSender; /* sender of the message (0 .. numThreads)*/
int type; /* its type */
int value1; /* first value */
int value2; /* second value */
};
struct msg mailboxes[MAXTHREAD + 1];
pthread_t threads[MAXTHREAD + 1];
sem_t semaphores[MAXTHREAD + 1];
int SendMsg(int iTo, struct msg &Msg);
int RecvMsg(int iFrom, struct msg &Msg);
bool safeToCall(int location);
#endif
I am compiling the code with the command
g++ -o addem addem.cpp mailbox.cpp -lpthread
I have tried commenting out all of the function bodies in the source code to leave them as stub functions, and the same error occurs. The only way I have been able to compile the file is if I comment out the function bodies, and remove
#include "mailbox.h"
From at least one of the files. I feel it has to do with how I am initializing the arrays? But I cannot figure out a workaround.

error: undefined reference to 'WinMain#16'

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__

Iterating through a VARIANT/SAFEARRAY of BSTR to Assign Values and Print to Console in C++

I'm attempting to fill a SAFEARRAY of 10 indexes of BSTR type with the value "test" and print out to console the value of each index of the SAFEARRAY after it has been assigned to verify correctness. I ran the debugger and got these values below for the first 5 indexes (my SAFEARRAY is called sa). Somehow I am iterating the SAFEARRAY incorrectly or using the wrong types, each index should be "test". Any advice on what im doing wrong?
sa[0] = "test"
sa[1] = "est"
sa[2] = "st"
sa[3] = "t"
sa[4] = ""
....
#include <iostream>
#include <string>
#include <Windows.h>
#include <atlbase.h>
#include <comutil.h>
#include <string.h>
#include <stdio.h>
using namespace std;
void fillVariant(VARIANT& varIn, BSTR &srcArray);
int main()
{
BSTR *theArray = new BSTR[10];
for(int i = 0 ; i < 10; i++)
{
theArray[i] = SysAllocString(L"test");
}
VARIANT variantArray;
fillVariant(variantArray, *theArray);
return 0;
}
void fillVariant(VARIANT& varIn, BSTR &srcArray)
{
VARIANT *variantArray = &varIn;
VariantInit(variantArray);
variantArray->vt = VT_ARRAY|VT_BSTR;
SAFEARRAY* sa;
SAFEARRAYBOUND aDim[1];
aDim[0].lLbound = 0;
aDim[0].cElements = 10;
sa = SafeArrayCreate(VT_BSTR, 1, aDim);
BSTR* dwArray = NULL;
SafeArrayAccessData(sa, (void**)&dwArray);
for(int i = 0; i < 10; i++)
{
dwArray[i] = &srcArray[i];
BSTR tmp = (BSTR) dwArray[i];
std::wstring ws(tmp);
//std::wstring ws(*dwArray[i], SysStringLen(dwArray[i]));
std::wcout << ws << endl;
}
SafeArrayUnaccessData(sa);
variantArray->parray = sa;
}
You are not filling in the VARIANT correctly. Try this instead:
#include <iostream>
#include <string>
#include <Windows.h>
#include <atlbase.h>
#include <comutil.h>
#include <string.h>
#include <stdio.h>
using namespace std;
void fillVariant(VARIANT& varIn, BSTR *srcArray, int srcArrayLen);
int main()
{
BSTR *theArray = new BSTR[10];
for(int i = 0 ; i < 10; i++)
{
theArray[i] = SysAllocString(L"test");
}
VARIANT variantArray;
fillVariant(variantArray, theArray, 10);
// don't forget to free memory when done!
// note: the VARIANT owns the BSTRs, so DON'T free them!
VariantClear(&variantArray);
delete[] theArray;
return 0;
}
void fillVariant(VARIANT& varIn, BSTR *srcArray, int srcArrayLen)
{
VARIANT *variantArray = &varIn;
VariantInit(variantArray);
SAFEARRAYBOUND aDim[1];
aDim[0].lLbound = 0;
aDim[0].cElements = srcArrayLen;
SAFEARRAY* sa = SafeArrayCreate(VT_BSTR, 1, aDim);
if (sa)
{
BSTR* dwArray = NULL;
SafeArrayAccessData(sa, (void**)&dwArray);
for(int i = 0; i < srcArrayLen; i++)
{
// note: passing ownership, NOT making a copy
dwArray[i] = srcArray[i];
//std::wstring ws(dwArray[i], SysStringLen(dwArray[i]));
std::wcout << dwArray[i] << endl;
}
SafeArrayUnaccessData(sa);
variantArray->vt = VT_ARRAY|VT_BSTR;
variantArray->parray = sa;
}
}
Alternatively:
#include <iostream>
#include <string>
#include <Windows.h>
#include <atlbase.h>
#include <comutil.h>
#include <string.h>
#include <stdio.h>
using namespace std;
void fillVariant(VARIANT& varIn, BSTR *srcArray, int srcArrayLen);
int main()
{
BSTR *theArray = new BSTR[10];
for(int i = 0 ; i < 10; i++)
{
theArray[i] = SysAllocString(L"test");
}
VARIANT variantArray;
fillVariant(variantArray, theArray, 10);
// don't forget to free memory when done!
VariantClear(&variantArray);
// note: the VARIANT DOES NOT own the BSTRs, so DO free them!
for(int i = 0 ; i < 10; i++)
{
SysFreeString(theArray[i]);
}
delete[] theArray;
return 0;
}
void fillVariant(VARIANT& varIn, BSTR *srcArray, int srcArrayLen)
{
VARIANT *variantArray = &varIn;
VariantInit(variantArray);
SAFEARRAYBOUND aDim[1];
aDim[0].lLbound = 0;
aDim[0].cElements = srcArrayLen;
SAFEARRAY* sa = SafeArrayCreate(VT_BSTR, 1, aDim);
if (sa)
{
for(LONG i = 0; i < srcArrayLen; i++)
{
// note: makes a copy, DOES NOT pass ownership!
SafeArrayPutElement(sa, &i, srcArray[i]);
//std::wstring ws(srcArray[i], SysStringLen(srcArray[i]));
std::wcout << srcArray[i] << endl;
}
variantArray->vt = VT_ARRAY|VT_BSTR;
variantArray->parray = sa;
}
}
&srcArray[i] doesn't do what you think it does. srcArray is a single BSTR, which is a typedef for WCHAR*. It is not an array of BSTRs. srcArray[i] refers to the ith character in theArray[0], and &srcArray[i] is the address of that character. That's how you got "test", "est" and so on.
Have fillVariant take BSTR* as its second parameter, and pass theArray, not *theArray.
On an unrelated note, your program leaks a bunch of BSTRs and a SAFEARRAY.