I have a simple dll build by c++ msvc2010. It create a mydll.dll. (it uses some of windows native dlls so this is a c wrapper. It has function in it
exten "c"
{
void myfunc(std::vector<std::string> &names)
)
Then I use mingw utility pexports.exe and dlltool.exe in mingw\bin folder to convert it.
pexports mydll.dll | sed "s/^_//" > mydll.def
dlltool -U -d mydll.def -l mydll.dll
(overwrite the original one. or rename the original one to mydllold.dll. All dlls are in the same folder of executable of code::blocks program below.)
Then I have a code::blocks project myproc. The compiler is MinGW's g++. It links to the mydll.dll in the property->link settings.
The compilation has no error. But when I run the program
myproc.exe. It has run time error:
mydll.dll is either not designed to run on windows or it contains an error.
When I use:
dlltool -U -d mydll.def -l mydll.a
Then rename mydll.dll to mydllold.dll.
And make myproc link settings to mydll.a, it get error message:
The program cannot start because mydll.dll is missing.
When I rename mydll.a to mydll.dll, it get same error message:
mydll.dll is either not designed to run on windows or it contains an error.
Note. it does not say mydll.a, instead mydll.dll even the link is to mydll.a.
If I rename mydllold.dll back to mydll.dll. The error message is:
The procedure entry point _myfunc could not be located in the dynamic link library mydll.dll.
header file mydll.h:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vector>
extern "C"
{
MYDLL_API int myfunc(std::vector<std::string>& a);
}
mydll.cpp:
#include <mydll.h>
extern "C"
{
MYDLL_API int myfunc( std::vector<std::string> &a)
{
return 0;
}
}
Related
Given the following files
RsbbDec.exe
Run_RsbbDec.exe
TRSCompress.dll
TRSCompress.lib
and the following example code:
#include <iostream>
#pragma comment(lib, "TRSCompress.lib.")
extern "C" __declspec(dllexport) int Run_RsbbDec(const char* Input_File, int vbr_en, int bitrate , char *ErrMsg);
#define TEXTLEN 1024
int main()
{
char ErrMsg[TEXTLEN];
if(Run_RsbbDec("audio.pcm", 1, 1, ErrMsg))
{
std::cout <<"ok";
}
else
{
std::cout <<"error";
}
}
How do I make the sample code work? The only instruction I was given was to make sure that the .dll and the 2 exes are in the same directory.
It seems to me that the main point of the demo code is to run the Run_RsbbDec function which I think is located in one of the executables.
I get a linker error when I run the code:
/tmp/ccuvBnWV.o:main.cpp:(.text+0x2b): undefined reference to `Run_RsbbDec'
I am using this command to compile:
g++ main.c RsbbDec.exe Run_RsbbDec.exe
Likely, the third-party supplied DLL was not built under Cygwin, but natively with Visual Studio (or similar).
That's okay, but you have to do some more work to form a compatibility between the two different environments.
You can read about it on the Cygwin website's page "Building and Using DLLs":
If you have an existing DLL already, you need to build a Cygwin-compatible import library. If you have the source to compile the DLL, see the section called “Building DLLs” for details on having gcc build one for you. If you do not have the source or a supplied working import library, you can get most of the way by creating a .def file with these commands (you might need to do this in bash for the quoting to work correctly):
echo EXPORTS > foo.def
nm foo.dll | grep ' T _' | sed 's/.* T _//' >> foo.def
Note that this will only work if the DLL is not stripped. Otherwise you will get an error message: "No symbols in foo.dll".
Once you have the .def file, you can create an import library from it like this:
dlltool --def foo.def --dllname foo.dll --output-lib foo.a
Alternatively, use native tools to build your own program.
Also, the pragma is wrong; there's an errant period at the end of the filename.
I have a C++ Visual Studio 2015 project consisting of
1 Windows API executable, 1 windows console executable, and 1 dll shared by both executables.
I have a #define USEWINDOWS in the Windows API main.cpp file
I don't have this defined in the console app
In the DLL, I would like to do an #ifdef USEWINDOWS statement, but the scope of the #define seems to be only valid to the Win32 executable, not in the dll.
How can I extend this #define to the DLL without having it affect the undefined USEWINDOWS in the console app?
Thanks
The DLL is shared by both executables, hence there is only one implementation available and therefore you can't use implementation specific compilation flags.
You'll need a runtime flag, i.e. some API parameter which tells the DLL code that it is OK to use "windows stuff". E.g.
api.h
void someAPI(...., bool useWindows);
dll.c
#include "api.h"
void someAPI(...., bool useWindows) {
...
if (useWindows) {
// do "windows stuff" here
}
...
}
app.c
#include "api.h"
...
someAPI(...., true);
console.c
#include "api.h"
...
someAPI(...., false);
(not tested by compilation, but you should get the drift...)
I have tried without success to create a C-language function in PostgreSQL from a module that depends on another DLL in Windows.
For example, let's suppose I want to create the sumfunction that adds two numbers returned by the numberfunction that is in its own DLL.
The code for number.h is:
#ifndef NUMBER_H
#define NUMBER_H
#ifdef NUMBER_EXPORTS
#define NUMBER_API __declspec(dllexport)
#else
#define NUMBER_API __declspec(dllimport)
#endif
extern "C" NUMBER_API int number();
#endif
and the code for number.cpp is:
#include "number.h"
extern "C" int number() { return 1; }
The code for sum.cpp is:
extern "C" {
#include <postgres.h>
#include <fmgr.h>
#include <utils/geo_decls.h>
#include "number.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
__declspec(dllexport) PG_FUNCTION_INFO_V1(sum);
Datum sum(PG_FUNCTION_ARGS)
{
int32 a {number()};
int32 b {number()};
int32 result {a + b};
PG_RETURN_INT32(result);
}
} // extern "C"
Suppossing that PostgreSQL is installed on C:\Program Files\PostgreSQL\9.5, I create number.dll and sum.dll using this build.bat file:
SET PG_DIR=C:\Program Files\PostgreSQL\9.5
SET PG_INCLUDES=/I%PG_DIR%\include /I%PG_DIR%\include\server /I%PG_DIR%\include\server\port\win32
CL number.cpp /EHsc /MD /DNUMBER_EXPORTS /LD
CL sum.cpp /EHsc /MD %PG_INCLUDES% /LD /link number.lib
Then I copy both DLLs to C:\Program Files\PostgreSQL\9.5\lib and write the SQL for creating the function in sum.sql:
CREATE OR REPLACE FUNCTION sum() RETURNS void AS
'sum'
LANGUAGE C STRICT;
After running psql -U postgres -f sum.sql, I get the following error:
psql:sum.sql:3: ERROR: could not load library "C:/Program Files/PostgreSQL/9.5/lib/sum.dll": The specified module could not be found.
Note that this error is different from a "file not found" error. It seems that PostgreSQL finds the file, but does not recognize it as a valid module. However, if I create a static library of num.cpp instead and link it against sum.dll, then the function is created successfully. In other words, PostgreSQL loads the module only if it contains all the code it needs.
Why is this happening and how could I make PostgreSQL to know about number.dll when creating the sum function?
The directories of the dependent DLLs must exist in PATH before PostgreSQL server is started.
Go to:
Control Panel
System and Security
System
Advanced System Settings
Advanced
Environment Variables
Path
Open it and add the full path of all directories where the dependent DLLs reside. Restart the PostgreSQL server and done, psql will execute the C-module successfully.
I have a very trivial problem including a chain of C libraries into a C++ main project. I've experience with C but it's the first time that I'm programming in C++.
The structure of the project is a single folder with inside:
main.cpp
Mylib_1.c
Mylib_1.h
Mylib_2.c
Mylib_2.h
main calls -> Mylib_1.h that calls -> My_lib2.h
//main.cpp
#include "Mylib_1.h"
//Mylib_1.h
#include "Mylib_2.h"
main contains both Mylib_1 and Mylib_2 functions and typedef structs
Mylib_1 uses typedef structs and functions of Mylib_2
Everything inside each Mylib_x.h is wrapped between extern "C", like this:
#ifndef __MYLIB_X_H
#define __MYLIB_X_H
#ifdef __cplusplus
extern "C" {
#endif
mycode
#ifdef __cplusplus
}
#endif
#endif
But when I try to compile it with eclipse kepler on Ubuntu 12.04 x64, I get:
Mylib_1.h error: Mylib_2_type_t does not name a type
main.cpp error: Mylib_2_function1 was not declared in this scope
...
Only the above sections are marked as error in eclipse, the header looks included fine.
Furthermore according to eclipse, the __cplusplus flag is false into Mylib_2.h but true into Mylib_1.h
Thinking of some eclipse error, I've tried to manually build the project via g++ (v4.6.3) but I got the same exact problem when I've tried to link the libraries .o with the main.cpp
Seems stupid but I can't figure out what could it be. Any suggestion?
Thank you
Have you checked that your lines
#ifndef __MYLIB_X_H
#define __MYLIB_X_H
are really different for the two files,
e.g. _MYLIB1_H and _MYLIB2_H?
How do I create static and dynamic libraries for Windows using g++?
I've found a few commands for Linux for creating .so files and I've tried to apply them on a Windows shell, but they build .dll files that my applications fail to link with at runtime.
I've only managed to build .dll files using Visual C++ but I would like to build them manually on the command line, preferably using g++. I would also like to know how to build static libraries too for Windows.
You need to prefix with the attribute :
__declspec(dllexport)...
all the features you want to expose.
See this.
Example for a C function:
__declspec(dllexport) int __cdecl Add(int a, int b)
{
return (a + b);
}
This can be simplified using MACROS: everything is explained on this helpful page.
For C++ classes, you only need to prefix each class (not every single method)
I usually do it that way :
Note : The following also ensures portability...
Include File :
// my_macros.h
//
// Stuffs required under Windoz to export classes properly
// from the shared library...
// USAGE :
// - Add "-DBUILD_LIB" to the compiler options
//
#ifdef __WIN32__
#ifdef BUILD_LIB
#define LIB_CLASS __declspec(dllexport)
#else
#define LIB_CLASS __declspec(dllimport)
#endif
#else
#define LIB_CLASS // Linux & other Unices : leave it blank !
#endif
Usage :
#include "my_macros.h"
class LIB_CLASS MyClass {
}
Then, to build, simply :
Pass the option -DBUILD_LIB to the usual compiler command line
Pass the option -shared to the usual linker command line