Cannot import Global variables from dll into application? - c

I have a DLL
A.dll
This is A.h
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
#define DLL_EXPORT extern "C" __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllexport)
#endif
DLL_EXPORT void function();
DLL_EXPORT char ** ReturnArr;
This is A.c
void function()
{
char *str = "hello";
char *str1 = "how are you?";
ReturnArr = (char **)malloc(sizeof(char*) * 2);
for(;j<2;j++)
{
ReturnArr[j] = (char *) malloc(256);
if(NULL == ReturnArr[j])
break;
}
strcpy(ReturnArr[0],"str");
strcpy(ReturnArr[1],"str1");
}
Now i have Application.c that would use dll
#include <windows.h>
#include <stdio.h>
typedef int (__cdecl *MYPROC)(LPWSTR);
_declspec(dllimport) char ** ReturnArr;
int main( void )
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
int a = 0;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
// Get a handle to the DLL module.
hinstLib = LoadLibrary(TEXT("A.dll"));
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "function");
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
(ProcAdd) (L"Message sent to the DLL function\n");
printf("%s",Returnarr[0]);
}
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
return 0;
}
In Visual studio CommonProperties->references:i added A.dll its showing me compiler ##error Error 1 error LNK2001: unresolved external symbol "__declspec(dllimport) char * ##* ReturnArr" (_imp?ReturnArr##3PAPADA)" and "Error 2 fatal error LNK1120: 1 unresolved ##externals"
how can i actually export a Global variable and use in my application,tell me a way how can i actually print ReturnArr as a global variable in my application
thanks

If you want the linker to resolve the ReturnArr imported variable, you have to add A.LIB to the link process. There are several ways to do this.
Add A.LIB to the "additionnal dependecies" in Configuration properties->Linker->Input
Add #pragma comment( lib, "a.lib" ) in Application.c
Make the DLL project a dependency of the EXE project and in the EXE project and set the Configuration properties->linker->General "Link Library dependencies" to yes.
Side notes:
Are you sure yoy want strcpy(ReturnArr[0],"str"); ? Could be
strcpy(ReturnArr[0],str); (without the quote around str)
If you statically link to A, you don't need to LoadLibrary and GetProcAddress.
You could also just supress _declspec(dllimport) char ** ReturnArr;
Your typedef for MYPROC is wrong. The return type of "function" is void, not int
If you want the EXE to know about the ReturnArr, just make it the return value of function!
You should try to explain what exactly you are trying to do

Related

Unresolved external symbol when assigning a function pointer to a function imported by DLL

I wasn't able to find a post with this particular issue. This is all in C, on a Windows target.
I have a DLL that I created, and some client code I created to test the DLL. The functions and types defined in the DLL are all successfully resolved by the client code except when I try to use a function pointer in the client code to a function defined in DLL.
Example:
/*--- DLL_Header.h ---*/
#ifdef BUILD_DLL
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
DLL_API void library_function(int foo, int bar);
/* --- DLL_source.c --- */
void library_function(int foo, int bar)
{
/* Do anything */
}
/* --- Client Code --- */
#include "DLL_Header.h"
void client_function_A()
{
int foo = 1;
int bar = 2;
library_function(foo,bar); /* This compiles and links with no problem! */
}
void client_function_B()
{
void (*lib_exec)(int foo, int bar);
lib_exec = &library_function; /* Compiles but then linker says unresolved external symbol __imp__library_function */
int x = 1;
int y = 2;
lib_exec(x,y);
}
client_function_B works fine if I just statically link everything, so it seems there is something I am not fundamentally understanding about the interaction between the DLL and function pointers. Can someone please help me understand what I am doing wrong, and why?
Edit: Exact error message
client_code.obj : error LNK2019: unresolved external symbol __imp__library_function referenced in function _client_function_B

Doubts on how to create C dll to be called from Lua code. Something wrong with syntax of typedef (pointer to function that returns const char *)

(I'm using Visual Studio 2015 Professional)
Firstly, I'd like to know if this is the correct way to import functions from C dlls: creating a pointer to them and assigning the value of such pointer via LoadLibrary and GetProcAddress. I'm trying it like this because I can't properly build my C code and call it from Lua interactive console. This was a desperate attempt. And yet, I got these errors that I'd like to understand.
Secondly, I don't know how to correct this warning:
C4090: 'function' different 'const' qualifiers
This is a shortened version of the dll I'm trying to compile.
//stdafx.h
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#ifdef __cplusplus
extern "C" {
#endif
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <windows.h>
#include <stdlib.h>
typedef const char * ( CALLBACK* luafnptr_typename ) ( lua_State *L, int tp );
#ifdef __cplusplus
}
#endif
And this code file:
//dllmain.c
#include "stdafx.h"
HINSTANCE hDLL;
luafnptr_typename l_typename = NULL;
BOOL load ( );
BOOL unload ( );
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
return load ( );
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
return unload ( );
break;
}
}
BOOL load ( )
{
hDLL = LoadLibrary ( "C:/Lua/5.2.4/lua5.2.4.dll" );
if ( hDLL != NULL )
{
l_typename = ( luafnptr_typename ) GetProcAddress ( hDLL, "lua_typename" );
if ( !l_typename )
{
FreeLibrary ( hDLL );
return FALSE;
}
}
return TRUE;
}
BOOL unload ( )
{
free ( l_typename );// <<< THIS LINE REPORTS THE WARNING
l_typename = NULL;
return TRUE;
}
Lastly, I also get a lot of LNK2001 unresolved external symbol [X] and LNK2019 unresolved external symbol [X] referenced in function [Y]
For example:
LNK2001 unresolved external symbol _floor LuaExperiment C:\Users\Kauan\Documents\Visual Studio 2015\Projects\LuaExperiment\LuaExperiment\lua5.2.4-static.lib(lvm.obj)
and:
LNK2019 unresolved external symbol _floor referenced in function _luaO_arith LuaExperiment C:\Users\Kauan\Documents\Visual Studio 2015\Projects\LuaExperiment\LuaExperiment\lua5.2.4-static.lib(lobject.obj)
I added Lua to the project simply by going to Project->Properties->Linker->Input->Aditional Dependencies->Edit... and added the value C:\Lua\5.2.4\*.lib nothing else.

How to use macro for calling function?

I want to call function according to func_name string.
My code is here below:
#define MAKE_FUNCNAME func_name##hello
void call_func(void* (*func)(void))
{
func();
}
void *print_hello(void)
{
printf("print_hello called\n");
}
int main(void)
{
char func_name[30] = "print_";
call_func(MAKE_FUNCNAME);
return 0;
}
But this code doesn't work. I want code to work like call_func(print_hello). But preprocessor treated my code like call_func("print_hello"). How to use macro in C to make my exception? Or is it not possible using C?
Then problem with your code is that the value of func_name is only known at run-time.
You can however to it like this:
#define MAKE_FUNCNAME(FUNCNAME) FUNCNAME##hello
void call_func(void* (*func)(void))
{
func();
}
void *print_hello(void)
{
printf("print_hello called\n");
}
int main(void)
{
call_func(MAKE_FUNCNAME(print_));
return 0;
}
But it is not possible to use a string value within macro parameters like in your code snippet.
If you want to get call functions with their names using string values you can use a table to store function pointer with function names like this:
struct {
const char *name;
void (*ptr)(void);
};
You can use an array of this structure to find out the function pointer at run-time using a string value. This is the most common solution to using run-time strings to call functions using their names.
You can't do that. The value of func_name is known at run-time (even though it is a const char *), while you want to determine what to call at precompile-time. You should turn your cpp macro into something different (such as an if/switch statement or using an indirection).
Maybe you could have a look to dlsym().
Not sure I really understand the question, but if you want to "build" the function name at runtime and then call the corresponding function, it should be possible with dlsym()
/* compile with: gcc example.c -ldl -rdynamic */
#include <dlfcn.h>
#include <stdio.h>
int print_hello(void)
{
return printf("hello\n");
}
int main(int argc, char *argv[])
{
const char *name = "print_hello";
if (argc == 42)
print_hello(); /* for compiler not to remove print_hello at
* compile time optimisation in this example*/
void *handle = dlopen(NULL /* self */, RTLD_NOW);
int (*f)(void) = dlsym(handle, name);
f();
return dlclose(handle);
}

Using C Functions Defined in Shared Object Without Renaming Them

I have been reading the on-line book Basics of libuv and trying to rewrite them to work with both a static link and a dynamic link to the libuv library. I rewrote the watchers example (code below), but I had to "rename" the functions I retrieved from libuv.dylib to make it work, which means I had to write an entirely separate code path for the dynamic linking case. Can I somehow keep the same function names?
I want my code to look like this.
#include <stdio.h>
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
#endif
int64_t counter = 0;
void wait_for_a_while(uv_idle_t *handle, int status) {
counter++;
if (counter >= 10e6)
uv_idle_stop(handle); // This function pointer must be a global variable
}
int main(int argc, char **argv) {
uv_idle_t idler;
// Initialize code needed for dynamically-linked library
#ifdef DYNAMIC
void *lib_handle = dlopen("libuv.dylib", RTLD_LOCAL|RTLD_LAZY);
// Set up pointers to functions defined in libuv.dyld ...
#endif
uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, wait_for_a_while);
printf("Idling...\n");
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
// Clean up dynamically linked code
#ifdef DYNAMIC
dlclose(lib_handle);
#endif
return 0;
}
Currently, it looks like this.
#include <stdio.h>
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
// Currently, I need to define function pointers with different names
// than the functions they call
uv_loop_t* (*uln)(void);
int (*ur)(uv_loop_t*, uv_run_mode);
uv_loop_t* (*udl)(void);
int (*uii)(uv_loop_t*, uv_idle_t*);
int (*uist)(uv_idle_t*, uv_idle_cb);
int (*uisp)(uv_idle_t*);
#endif
int64_t counter = 0;
void wait_for_a_while(uv_idle_t *handle, int status) {
counter++;
if (counter >= 10e6)
#ifdef DYNAMIC
uisp(handle);
#else
uv_idle_stop(handle); // This should be the only line remaining
#endif
}
int main(int argc, char **argv) {
uv_idle_t idler;
// Code path for dynamic linking case
#ifdef DYNAMIC
void *lib_handle = dlopen("libuv.dylib", RTLD_LOCAL|RTLD_LAZY);
// Retrieve symbol names from libuv.dylib
*(void **)(&uln) = dlsym(lib_handle, "uv_loop_new");
*(void **)(&ur) = dlsym(lib_handle, "uv_run");
*(void **)(&udl) = dlsym(lib_handle, "uv_default_loop");
*(void **)(&uii) = dlsym(lib_handle, "uv_idle_init");
*(void **)(&uist) = dlsym(lib_handle, "uv_idle_start");
*(void **)(&uisp) = dlsym(lib_handle, "uv_idle_stop");
uii(udl(), &idler);
uist(&idler, wait_for_a_while);
printf("Idling...\n");
ur(udl(), UV_RUN_DEFAULT);
dlclose(lib_handle);
// Code for static linking case
#else
uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, wait_for_a_while);
printf("Idling...\n");
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
#endif
return 0;
}
Change:
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
/*...*/
into:
#ifndef DYNAMIC
#include <uv.h>
#else
#include <dlfcn.h>
/*...*/
Now, you can name your function pointer variables the same as the interfaces you want to call them as.
However, it is unclear why you need to do this at all. Normally, you just link your application with the dynamic library. You would only need to do what you are doing if you are experimentally changing the implementation of the dynamic library (treating it like a plugin).
In a comment, you mention that you need the definitions of structures in <uv.h>. Then to make my original proposal work, you would need to redefine those structures in the case of DYNAMIC, since you would not be using the header file. But, if the uv library ever changes, you would lose those changes and be forced to update your DYNAMIC version to match, which is an undesirable situation.
Another work around is to follow your original approach of defining different function pointer names, but then define macros to map the original function names to the function pointer names.
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
uv_loop_t* (*uln)(void);
int (*ur)(uv_loop_t*, uv_run_mode);
//...
#define uv_loop_new uln
#defin uv_run ur
//...
#endif

Make my C function call from my CUDA code

I have cuda code which makes a call to a function present in a .c file whose header file I have included in my cuda code. So, in all I have a header file, a C file for that header file, and a CUDA code. When I am compiling my CUDA code using nvcc and specifying my cuda code name and c file name, then I am getting undefined reference to the functions I called in my CUDA code which are actually present in my C file. Please help me understand what am I doing wrong and how can I fix my mistake.
Ok I am pasting my code below... I did not post it initially because I thought its a linker error or something.
#include "dbConnection.h"
#include "error.h"
#include "libpq-fe.h"
#include <stdio.h>
#include <stdlib.h>
#include "appCompileSwitches.h"
int makeConnection(PGconn** conn,const char* connInfo);
void executeQuery(PGconn* conn,PGresult** res,char* statement,int* rows,int* columns);
/***************************************
* main(), enough said
****************************************/
int main(int argc, char **argv)
{
PGconn *conn = NULL;
PGresult *res= NULL;
float** result;
char* statement = "select visit_no,brand_name from visit_sample limit 3";
int rows=0,columns=0; // WILL BE USED TO CUDAMALLOC gpu memory
const char* connInfo = "dbname = moxy";
if(!makeConnection(&conn,connInfo))
{
printf("failed to connect to Database!\n");
return FAILURE;
}
}
The dbConnection.c file has :
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"
#include <string.h>
#include "dbConnection.h"
#include "error.h"
#include "appCompileSwitches.h"
/****************************************************
* close database connection, given connecton info
****************************************************/
static void closeConnection(PGconn *conn)
{
/* close the connection to the database and cleanup */
PQfinish(conn);
}
/****************************************************
* connect to the database
* given the connInfo
****************************************************/
extern int makeConnection(PGconn** conn,const char* connInfo)
{
/* Make a connection to the database */
*conn = PQconnectdb(connInfo);
if (PQstatus(*conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s",PQerrorMessage(*conn));
PQfinish(*conn);
return FAILURE;
}
return SUCCESS;
}
So when I am doing:
nvcc DB.cu dbConnection.c -o DB
I am getting undefined reference to make connection.
Also, I will be transferring the data I get from DB to GPGPU later and that is the whole point of this exercise so please do not say I have no CUDA calls here. This is a code still under development.
Your external function is in a .c file, so the host compiler compiles it using the C language naming/calling convention. nvcc, on the other hand, is a C++ compiler by default, so it defaults to C++ naming/calling convention. You need to tell the C++ compiler to look for an external "C" function for makeConnection, by declaring it as such in your header and/or forward declaration in the .cu file.
extern "C"
int makeConnection(PGconn** conn,const char* connInfo);

Resources