MASM: Accessing to global C variable from assembly - c

I'm writing a program to convert image and compare the speed of processing data in C and assembly. I have 3 projects:
main project in C
DLL in C to convert image
DLL in ASM to convert image
In C DLL header, I simply wrote:
#ifdef PROJEKTC_EXPORTS
#define PROJEKTC_API __declspec(dllexport)
#else
#define PROJEKTC_API __declspec(dllimport)
#endif
...
extern PROJEKTC_API unsigned int ThreadID;
PROJEKTC_API void __cdecl funkcjaC(void* Args);
and after including this header, I can access variable ThreadID both in main project and C DLL.
The problem starts when I try to do the same in ASM. I tried constructions like extern ASMThreadID:dword in .code block, but it won't work.
The error I got: error LNK2019: unresolved external symbol _ASMThreadID referenced in function _MyProc1
I have a feeling that it's a matter of 1-2 lines of code, but I can't figure out which instruction should I use.
I link the projects by module definition file in ASM and adding ASM.lib file into the Linker->Input of main project.
Do you have any suggestions?

With small help from old posts in asmcommunity.net, I managed to get it working:
In .asm file, before .data segment:
EXTERNDEF C ASMThreadID:DWORD
In .data segment:
ASMThreadID dd 0
In .def file of ASM DLL:
LIBRARY "nameOfProject"
EXPORTS
...
ASMThreadID
In main C program header (like global declaration):
extern __declspec(dllimport) unsigned int ASMThreadID;
Now it works like a charm.
The 'public' declaration sent me to the right way of searching. Thanks for your help, mate!

Related

C Code using Glib library building succesfully on windows gives compiler/linker error on linux

I have a code which makes use of Glib library to create a new type. Now the code is as:
.h file:
G_DECLARE_DERIVABLE_TYPE(NewTypeState, new_type_state, NEW, TYPE_STATE, ParentType)
.c file:
G_DEFINE_TYPE_WITH_PRIVATE(NewTypeState, new_type_state, NEW_TYPE_STATE)
now as per the glib doc for object creation we have to define two static functions as:
static new_type_init()
static new_type_class_init()
But in the code instead of defining static new_type_init() the func. is declared as:
__declspec(dllexport) extern void new_type_init()
and defined as:
void new_type_init()
{}
And the code compiles and links successfully on windows but while trying to build on linux I removed the __declspec(dllexport) but I started getting the error:
static declaration follows non-static declaration
Now I commented out the declaration from .h file and only has non-static definition in the .c file but when trying to build it I get the linker error:
undefined reference new_type_init
I even added the extern to definition but the error stays.
Could someone explain the above behavior?
EDIT:
o/p for objdump -t <file-name> | grep -i <symbol-name> is:
000000000000b440 l F .text 0000000000000023 symbol-name
0000000000000000 *UND* 0000000000000000 symbol-name
Extern indicates the function will be available later (i.e. is not defined here in this translation unit). Static forces the function to be unavailable externally. Add extern to the declaration in the header and remove static from the definition and you may have some success. That being said, I do not know Glib so cannot say for sure.

Which import directive will import a symbol from a DLL and not add a prefix? (Visual Studio)

The short question is: Which directive adds no prefix to an imported symbol?
I have a library that is 100% C (no C++ and not C compiled with a C++ compiler) It's C top to bottom. (I have to mention that because sometimes folks confuse how Visual Studio works when compiling C using the C++ compiler with C using a C compiler.)
The library was compiled with CMAKE and it outputted a DLL with a symbol table that looks like this:
dumpbin.exe /exports mydll.dll
...stuff...
1 0 00001087 mylib_get_x
..etc..
There's a static lib file too.
dumpbin.exe /exports mydll.lib
...stuff...
mylib_get_x
Notice how there are no weird prefixes? (i.e. no imp on the symbols) This makes the DLL extremely useful when trying to import the functions into things like the FFI in LuaJIT and other compilers/environments.
And I have an app that uses "mylib_get_x()"
/* myfile.c */
... stuff ...
int x;
x = mylib_get_x();
The result is: unresolved external symbol _mylib_get_x referenced in function ...
If I prefix the mylib_get_x() with any of these:
__declspec(dllimport)
__cdecl
__stdcall
_cdecl
extern
extern "C" __declspec(dllimport)
<nothing>
It doesn't matter. It won't work. They add prefixes. Which one adds nothing?
When it was compiled, it had __declspec(dllexport) on it, but it's a 3rd party library, so somehow they got it to avoid the extra prefixes.
I can link in the supplied .lib file that was generated. Same result. (see the dumpbin above that shows the symbol table from the .lib file without prefixes) I can create a manual .def file, generate a lib file from it and link to that. Same result.
I would love it if someone could explain what prefixes go with what directive.
Which directive adds no prefix to the symbol?

What are the exact steps for creating and then linking against a Win32 DLL on the command line?

Here's my library Lib.c file:
#include <stdio.h>
int helloworld(){
printf("Hello World DLL");
}
Here's my exe Main.c file:
int helloworld();
int main(int argc, char** argv){
helloworld();
}
I would like to create Lib.dll, and Main.exe, where Lib.dll comes from Lib.c and Main.exe links against Lib.dll.
What are the specific steps to achieve this?
See this related question on how to build the DLL.
Your library code as it stands does not export any symbols and your executable does not import the symbols from your library. Two typical patterns for doing that are shown below but you might want to read up on that first.
The first method uses __declspec() to declare in the code what functions (or other items) are exported from your DLL and imported by other executables. You use a header file to declare the exported items and have a preprocessor flag used to control whether the symbols are exports or imports:
mylib.h:
#ifndef MYLIB_H
#define MYLIB_H
#if defined(BUILDING_MYLIB)
#define MYLIB_API __declspec(dllexport) __stdcall
#else
#define MYLIB_API __declspec(dllimport) __stdcall
#endif
#ifdef __cplusplus
extern "C" {
#endif
int MYLIB_API helloworld(void);
#ifdef __cplusplus
}
#endif
#endif
I have also specifically set the calling convention to __stdcall as are most DLL functions (I could have used WINAPI instead of __stdcall if I had included windows.h) and have declared the functions as extern "C" so their names do not get mangled when compiled as C++. Not such a problem here as it's all C, but if you were to build the DLL from C source and then try to use it from a C++ executable then the imported names would be incorrect.
The code could then look like this:
mylib.c
#include "mylib.h"
#include <stdio.h>
int MYLIB_API helloworld(void)
{
printf("Hello World DLL");
return 42;
}
You'd build your DLL using the following command line. As well as creating the DLL it will create the import library (.lib) required to use your DLL from another executable (as well as the export file, but that is only required in certain circumstances):
cl /DBUILDING_MYLIB mylib.c /LD
The /DBUILDING_MYLIB argument defines the preprocessor symbol used to control whether the functions in the DLL are exports (if it is defined) or imports (not defined). So you'd define it when building the DLL but not when building your application.
The /LD parameter tells cl to produce a DLL.
The second method is to use module definition files as mentioned in the comments. You can use the code you already have but you also need to create the module definition file. At it's simplest it looks like this:
LIBRARY mylib
EXPORTS
helloworld
In this case to build the DLL you require the following command line:
cl /LD mylib.c /link /DEF:mylib.def
You could then code your application so that it used your library header with the imported version of your DLL function:
main.c
/* No need to include this if you went the module definition
* route, but you will need to add the function prototype.
*/
#include "mylib.h"
int main(void)
{
helloworld();
return (0);
}
Which you could then compile with the following command line (assuming the import library from the DLL creation is in the same directory as your main.c). This step is the same whether you used declspec or module definition files:
cl main.c /link mylib.lib
Arguments passed after the /link argument are passed onto the linker command line as they appear, so as just a filename it is used as extra input to link into the executable. In this case we specify the import library generated when we built the DLL.
The command lines I've shown here are pretty much the absolute minimum you'd need but it'll allow you to create a DLL and link an application to it.
I have assumed the calling convention is correct in all of the above and I have not experimented much to see whether I got it wrong at any point.

Unable to resolve symbol when using lib... any ideas?

Written in C (into a C++ project):
I have two projects in VS08 under the same solution. One is a DLL file and the other ("runner") is the a console application for using/testing the DLL file. The header file has a header file with all the functions (__declspec(dllexport)). When I use functions without any arguments, by the runner console application, they run OK. When I try to call a function with arguments I get unable to resolve symbol... error. The strange thing is that VS08 recognizes the function and I can open it from the runner main() with the right-click menu, however it can't find it.
Worth mentioning that I am including the header file and not importing the DLL with function pointers... My feeling is that the functions get renamed somehow in the compiling process and the linker can't find the functions with the arguments. If I would be able to to see the list of new names (inside the object file?) maybe I could include them in the header file to fix this?
Thanks.
Written in C (into a C++ project):
That's possibly a pretty good lead. A C program cannot consume functions that were written in C++. When you use __declspec(dllexport), the function gets exported with its C++ name. Which is decorated by the compiler, a trick to allow overloaded functions to link properly. A C compiler doesn't apply the same kind of decoration, the linker will complain that it can't find the function.
To make this work, you have to declare the function with the extern "C" declarator. Make the .h file look like this:
#ifdef __cplusplus
extern "C" {
#endif
#undef DLLEXPORT
#ifdef BUILDING_MYDLL
# define DLLEXPORT __declspec(dllexport)
#else
# define DLLEXPORT __declspec(dllimport)
#endif
DLLEXPORT void Foo(int arg);
// etc..
#ifdef __cplusplus
}
#endif
In your DLL project, use Project + Properties, C/C++, Preprocessor and add BUILDING_MYDLL to the Preprocessor Definitions settings.
A short explanation for this macro madness: the #ifdef __cplusplus ensures that all the DLL declarations are declared extern "C" when they are compiled by the C++ compiler so that they'll match the C compiler symbols. The DLLEXPORT macro ensures that the functions are exported when you build the DLL, imported when you link the DLL import library in another project.
You can get additional troubleshooting from the dumpbin.exe utility by running it with the /exports option on your DLL. It shows the exact names of exported functions. Run it from the Visual Studio command prompt. A mismatch between the names you see in the output verses the linker error messages is a sure sign of trouble.
First off: Intellisense finding it ('open for the rightclick menu' eeeeck?) is no proof; it proves you put the declaration in a header file;
You are probably right about the name mangling thing: If you have C externals you need to declare them inside an extern "C" {} block:
extern "C" {
void dostuff(int param1, char* param2);
}
instead of
extern void dostuff(int param1, char* param2);
The most flexible approach is probably to include the extern "C" around the complete C header file conditionally:
// Sample.h
#if defined(__cplusplus)
extern "C"
{
#endif
// Function declarations
#if defined(__cplusplus)
}
#endif
See MSDN for more info

dllimport /dllexport and static libraries compilation under visual c++

I desperatly need your help.
Im trying to compile statically the poppler library (specially for qt4) on windows with the visual c++ 2008 compiler. To achieve this task I needed to compile a bunch of other libraries as dependencies for poppler statically too. When I finally generate the static version of poppler I got a linking error when building my app:
error LNK2019: unresolved external symbol "__declspec(dllimport)...
I already added the new include path and linked the poppler-qt4.lib but i get the error anyways.
Searching for a solution I found this discussion here in stackoverflow
How to link a static library in Visual C++ 2008?
whit this information I looked on the include files of the libraries (dependencies of poppler like zlib, libpng, cairo, ...) and I found, in various cases, that they don't have a preprocessor directive to especify the static version of the lib.
Example static directive (openjpeg.h):
#if defined(OPJ_STATIC) || !(defined(_WIN32) || defined(WIN32) || defined(__WIN32__))
# define OPJ_API
# define OPJ_CALLCONV
#else
# define OPJ_CALLCONV __stdcall
# ifdef OPJ_EXPORTS
# define OPJ_API __declspec(dllexport)
# else
# define OPJ_API __declspec(dllimport)
# endif /* OPJ_EXPORTS */
#endif /* !OPJ_STATIC || !WIN32 */
Example without static directive (jconfig.h from jpeg lib):
#if defined(_WIN32)
#if defined(libjpeg_EXPORTS)
#define JPEG_EXPORT __declspec(dllexport)
#else
#define JPEG_EXPORT __declspec(dllimport)
#endif
#else
#define JPEG_EXPORT
#endif
My question is: Is not enough to change the properties of the project from dynamic to static so I have to change this headers too?, and if this is true, where can I define this new directives for making a difference between static or dynamic compilation?
Thanks in advance.
First please note Windows does not have any dynamic linkage at all. Surprise! Instead, it uses thunks. So what happens is: if you make a symbol dllexport, it has its actual name, the same name as if it were not dllexport. However it is marked in the object file for exporting.
If you say dllimport, on the other hand, the name is changed, in C roughly by prepending __imp_ to the name, more nasty in C++.
Now, when you link a DLL, you get a DLL (of course) but you also get a LIB file. That is a static link library. Which is the only kind the linker can handle. For each symbol exported from the DLL there is a dllimport symbol in that LIB file, in particular with __imp_ prefix or whatever for C++.
So now in a program or DLL you want to link to that DLL you made you link instead against the import LIB. The import LIB routines are thunks that patch up to the actual load time addresses from the DLL.
So now, if you try to do ordinary static linkage against a LIB file made by LIB.EXE by simply combining OBJ files which contained some dllexport, it will fail if the reference is a dllimport. Because you're refering to __imp_function() when the library actually contains plain function().
So with static linkage, you have to drop the dllimport. AFAIK dllexport is irrelevant. Note that this applies to the client of the library, not the library itself.
What does that mean? Well it is perfectly fine to statically link to a library which in turn dynamically links to another library. In fact by default static links on Windows dynamically link to the C runtime and OS DLLs. So the rule is: the client must chose the method of linking to a library, the provider should provide both versions. But take care they have different names!! (Otherwise the LINK making the DLL will make fred.LIB and the LIB will also make fred.LIB)
If you are changing the project properties from dynamic to static linkage as specified in the openjpeg.h you have to specify preprocessor that can use the static linkage..so in addition to changing the property from dynamic to static, add the preprocessor OPJ_STATIC...
For example:
#if defined(_WIN32)
#if defined(OPJ_STATIC)
# define OPJ_CALLCONV __stdcall
#el if defined(libjpeg_EXPORTS)
#define JPEG_EXPORT __declspec(dllexport)
#else
#define JPEG_EXPORT __declspec(dllimport)
#endif
#else
#define JPEG_EXPORT
#endif

Resources