SDL2: undefined references to strange functions - codeblocks

i have written this small piece of Code for testing purposes:
#include <iostream>
#include "SDL2/SDL.h"
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
printf("Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}
// Betriebssystem ermitteln
std::string PlatFormString;
PlatFormString = SDL_GetPlatform();
std::cout << PlatFormString << "\n";
// Separator ermitteln
char Separator = '/';
if (PlatFormString == "Windows") {
Separator = '\\';
}
std::cout << "Separator: " << Separator << "\n";
// Installationspfad ermitteln
std::string InstallPath;
InstallPath = SDL_GetBasePath();
std::cout << InstallPath << "\n";
// Benutzerverzeichnis ermitteln
char* UserPath;
UserPath = SDL_GetPrefPath("TFF", "Blaster");
if (UserPath == nullptr) {
std::cout << "No Userpath aviable !! \n";
}
else {
std::cout << UserPath << "\n";
}
SDL_Quit();
return 0;
};
Under Linux eerthing works fine.
But under Windows, i am getting these strange errors ...
-------------- Build: Debug in Test (compiler: GNU GCC Compiler)---------------
g++.exe -LD:\mingw64 -LD:\mingw64\bin -LD:\mingw64\include -LD:\mingw64\include\SDL2 -LD:\mingw64\lib -o bin\Debug\Test.exe obj\Debug\src\Test.o -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -lSDL2_mixer ..\..\mingw64\lib\libSDL2main.a ..\..\mingw64\lib\libSDL2.a
..\..\mingw64\lib\libSDL2.a(SDL_systimer.o): In function `timeSetPeriod':
/Users/slouken/release/SDL/SDL2-2.0.3-source/foo-x64/../src/timer/windows/SDL_systimer.c:58: undefined reference to `__imp_timeBeginPeriod'
/Users/slouken/release/SDL/SDL2-2.0.3-source/foo-x64/../src/timer/windows/SDL_systimer.c:52: undefined reference to `__imp_timeEndPeriod'
/Users/slouken/release/SDL/SDL2-2.0.3-source/foo-x64/../src/timer/windows/SDL_systimer.c:58: undefined reference to `__imp_timeBeginPeriod'
and so on. I dont know whats going on there. Can anyone help ?
I#m using Codeblocks 13.12, minGW64 (4.8.1), SDL 2.0.3 and Windows 7 64bit

You need to link against winmm.lib.
Try adding
#pragma comment(lib, "winmm.lib")
to your source.

I am posting this about a year later but for the future searchers here is the solution. Replace libSDL2.a with libSDL2.dll.a and it will compile just fine. The issue has something to do with dynamic and static linking with a windows machine or something I personally do I understand it completely but it works.
I came across the solution by reading this article: http://tech.yipp.ca/sdl/how-to-fix-libsdla-undefined-reference/
However this goes on a whole other solution I read between the lines or more particularly.
This is a really a rare problem that would occur only when you try to link with libSDL.a static library instead of the dynamic library SDL.dll. Then you have to add those library that SDL.dll normally links against which are the three above.

Related

Use libp11 on Windows environment

I want to install all I need to use libp11 and use libp11.
What is my environment and needs:
I work on Windows 10, 64 bits.
I add package with pacman linux command on my mingw32 terminal (msys64 version of 2022/09/04).
I work on a Qt Creator editor and I have a .pro file to configure my Qt project.
I want to develop a C++ module for my application which use libp11 to get the Yubikey bin number and decrypt file.
Why I use a mingw32 terminal and not the mingw64, because, for the moment, the project is always in develop in QT 4.8.
What I do:
I read the README file and follow the installation step of the INSTALL file (first I follow the MinGW / MSYS chapter, then I follow the MSYS2 chapter.)
I do much more, but I don't remember every thing and I go in many wrong ways.
My problems and questions
I try to follow the examples find in GitHub.
I help me with the site cpp.hotexemples.com to find the second parameter for the PKCS11_CTX_load function. I find the st_engine_ctx structure on this project.
The project file:
TEMPLATE = app
CONFIG += console c++17
CONFIG -= app_bundle
CONFIG += qt
LIBS += \
-lp11 \
-lssl \
-lcrypto
SOURCES += \
TestYubikey.cpp \
main.cpp
HEADERS += \
TestYubikey.h
The header file:
#ifndef TESTYUBIKEY_H
#define TESTYUBIKEY_H
#include <libp11.h>
#include <cstdio>
#include <cstring>
#include <openssl/err.h>
#include <openssl/crypto.h>
#include <openssl/objects.h>
#include <openssl/engine.h>
#include <openssl/ui.h>
/* Engine configuration */
/* The PIN used for login. Cache for the ctx_get_pin function.
* The memory for this PIN is always owned internally,
* and may be freed as necessary. Before freeing, the PIN
* must be whitened, to prevent security holes.
*/
struct st_engine_ctx
{
char *pin = nullptr;
size_t pin_length = 0;
int verbose = 0;
char *module = nullptr;
char *init_args = nullptr;
UI_METHOD *ui_method = nullptr;
void *callback_data = nullptr;
int force_login = 0;
/* Engine initialization mutex */
#if OPENSSL_VERSION_NUMBER >= 0x10100004L && !defined(LIBRESSL_VERSION_NUMBER)
CRYPTO_RWLOCK *rwlock = nullptr;
#else
int rwlock;
#endif
/* Current operations */
PKCS11_CTX *pkcs11_ctx = nullptr;
PKCS11_SLOT *slot_list = nullptr;
unsigned int slot_count = 0;
};
class TestYubikey
{
public:
TestYubikey();
};
#endif // TESTYUBIKEY_H
The source file:
//libp11 is a wrapper library for PKCS#11 modules with OpenSSL interface
#include "TestYubikey.h"
#include <iostream>
TestYubikey::TestYubikey()
{
// Create a new libp11 context
PKCS11_CTX *ctx = PKCS11_CTX_new();
std::cout << "ctx = " << ctx << std::endl;
/* load pkcs #11 module */
int rc = PKCS11_CTX_load(ctx, "C:\\msys64\\mingw32\\lib\\engines-1_1\\pkcs11.dll"); //I test with "libpkcs11.dll" and "pkcs11.dll" too.
std::cout << "rc = " << rc << std::endl;
if (rc == -1)
{
std::cout << "Loading pkcs11 engine failed";
unsigned long error_code = ERR_get_error();
const char* error_detail = ERR_reason_error_string(error_code);
std::cout << " (" << error_code << ") : " << std::string(error_detail) << std::endl;
}
else
{
std::cout << "Loading pkcs11 engine worked !" << std::endl;
}
}
My output console show:
11:59:27: Starting C:/Users/jgomez/Documents/build-SandBox-Desktop_Qt_4_8_7_MinGW_32_bit-Release/release/SandBox.exe...
ctx = 0x2ca8f50
rc = -1
Loading pkcs11 engine failed (0) : terminate called after throwing an instance of 'std::logic_error'
what(): basic_string: construction from null is not valid
11:59:29: C:/Users/jgomez/Documents/build-SandBox-Desktop_Qt_4_8_7_MinGW_32_bit-Release/release/SandBox.exe exited with code 3
My problem:
rc = -1
Solution :
use the Dll called opensc-pkcs11.dll provided with OpenSC project and it should work.
( https://github.com/OpenSC/OpenSC , after installing , it should be found here by default C:\Program Files (x86)\OpenSC Project\OpenSC\pkcs11)
Explantation :
I have encountered the same problem, and after messing around with the files I figured out that this error due the PKCS11_CTX_Load function.
PKCS11_CTX_Load , tries to load the pkcs11.dll , and then tries getting the address of "c_get_function_list" from this dll, which fails since it doesn't have that function.

Can I use "this" with delegating constructors?

C++11 introduced the possibility of delegating construction from one constructor to another - "delegating constructors".
But - when doing that, can we use the this pointer? e.g. as an argument to one of the constructors we're delegating to? It's not trivial to assume that we can while the "real constructor" has not actually been invoked yet.
For a definitive answer one would need to read the standard (and even there it might not be entirely clear, see #BenjaminBanner's comment). But in practice - yes, apparently we can use this in constructor delegation.
The following example:
#include <iostream>
struct A {
A(int x_, void* p_) : x(x_), p(p_) { }
A(void* p_) : A(0, p_) { }
A() : A(this) { }
int x;
void* p;
};
int main() {
A a;
std::cout << "&a == " << &a << "\n";
std::cout << "a.p == " << a.p << "\n";
}
compiles (GodBolt) with all of GCC, clang and MSVC. They do not warn about doing this, even with -Wall -Wpedantic -Wextra or /W4 for MSVC.
It also runs (coliru.com) and produces the expected output (at the link you have the g++-compiled version, clang++ can be checked there as well).

exiftool from Cocoa

I am trying to use exiftool form Cocoa
#include <iostream>
#include "ExifTool.h" // this is a .mm file so that we can include C++ code/structures
#implementation MyClass
-(id)myInit
{
if (self = [super init])
{
ExifTool* tool = new ExifTool("/Users/trygve/Tools/exiftool");
}
}
This is obviously just a test but in the "new ExifTool" line I get a crash:
dyld`dyld_fatal_error:
0x7fff5fc01074 <+0>: int3
-> 0x7fff5fc01075 <+1>: nop
Thread 1: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
dyld: Symbol not found: __ZN8ExifToolC1EPKcS1_
The following code works fine in a straight C++ terminal program. This is from the examples on the exiftool developer page. Why does this code work fine, but when I try to use it from a Cocoa .mm file, it does not?
#include <iostream>
#include "ExifTool.h"
int main(int argc, char **argv)
{
if (argc < 2) {
std::cout << "Example1: Read metadata from an image." << std::endl;
std::cout << "Please specify input file name" << std::endl;
return 1;
}
// create our ExifTool object
ExifTool *et = new ExifTool("/Users/trygve/Tools/exiftool");
// read metadata from the image
TagInfo *info = et->ImageInfo(argv[1],NULL,5);
if (info) {
// print returned information
for (TagInfo *i=info; i; i=i->next) {
std::cout << i->name << " = " << i->value << std::endl;
}
// we are responsible for deleting the information when done
delete info;
} else if (et->LastComplete() <= 0) {
std::cerr << "Error executing exiftool!" << std::endl;
}
// print exiftool stderr messages
char *err = et->GetError();
if (err) std::cerr << err;
delete et; // delete our ExifTool object
return 0;
}
It turns out that the C++ code files associated with this were getting copied into the app rather than compiled. It works as expected. With just the header files there was no error, and a pretty cryptic crash.

C++ gettid() was not declared in this scope

A simple program is:
I would like to get the thread ID of both of the threads using this gettid function. I do not want to do the sysCall directly. I want to use this function.
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/date_time/date.hpp>
#include <unistd.h>
#include <sys/types.h>
using namespace boost;
using namespace std;
boost::thread thread_obj;
boost::thread thread_obj1;
void func(void)
{
char x;
cout << "enter y to interrupt" << endl;
cin >> x;
pid_t tid = gettid();
cout << "tid:" << tid << endl;
if (x == 'y') {
cout << "x = 'y'" << endl;
cout << "thread interrupt" << endl;
}
}
void real_main() {
cout << "real main thread" << endl;
pid_t tid = gettid();
cout << "tid:" << tid << endl;
boost::system_time const timeout = boost::get_system_time() + boost::posix_time::seconds(3);
try {
boost::this_thread::sleep(timeout);
}
catch (boost::thread_interrupted &) {
cout << "thread interrupted" << endl;
}
}
int main()
{
thread_obj1 = boost::thread(&func);
thread_obj = boost::thread(&real_main);
thread_obj.join();
}
It gives Error on compilation; The use of gettid() has been done according to the man page:
$g++ -std=c++11 -o Intrpt Interrupt.cpp -lboost_system -lboost_thread
Interrupt.cpp: In function ‘void func()’:
Interrupt.cpp:17:25: error: ‘gettid’ was not declared in this scope
pid_t tid = gettid();
This is a silly glibc bug. Work around it like this:
#include <unistd.h>
#include <sys/syscall.h>
#define gettid() syscall(SYS_gettid)
The man page you refer to can be read online here. It clearly states:
Note: There is no glibc wrapper for this system call; see NOTES.
and
NOTES
Glibc does not provide a wrapper for this system call; call it using syscall(2).
The thread ID returned by this call is not the same thing as a POSIX thread ID (i.e., the opaque value returned by pthread_self(3)).
So you can't. The only way to use this function is through the syscall.
But you probably shouldn't anyway. You can use pthread_self() (and compare using pthread_equal(t1, t2)) instead. It's possible that boost::thread has its own equivalent too.
Additional to the solution provided by Glenn Maynard it might be appropriate to check the glibc version and only if it is lower than 2.30 define the suggested macro for gettid().
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 30
#include <sys/syscall.h>
#define gettid() syscall(SYS_gettid)
#endif

boost library inside c++/cli.. exit with "code 0xC0020001: The string binding is invalid"

I am using the boost library for getting the current system time and my code works but visualt studio 2010 exits after the program.the debugger breaks while trying to free the non existing pointer. I know this is because of the boost native code.Since there is no error if I comment the boost portion of code.
Till now I tried using the #pragma as explained in MSDN but with no success.Can someone provide me some suggestions.? (I also tried GetSystemTime function to get the time but i cannot get the microsecond detail like boost.)
MY Code
#pragma managed(push, off)
void GetSystemDateTime(SDateTime& stimeblock);
#pragma managed(pop)
int main()
{
c++/cli code
SDateTime stimestruct[1];
//call to the function having the boost code..
GetSystemDateTime(stimestruct[0]);
}
Function Definition
#pragma managed(push, off)
void GetSystemDateTime(SDateTime& timeblock)
{
// SYSTEMTIME time;
// GetSystemTime(&time);
// WORD millis = (time.wSecond * 1000) + time.wMilliseconds;
boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();
std::tm pt_tm = to_tm(now);
std::cout << now << std::endl;
//std::cout << time.wYear<< time.wMonth<<time.wDay //<<time.wHour<<time.wMinute<<time.wSecond<<time.wMilliseconds << std::endl;
std::string timestring = to_iso_string(now);
std::string sYear = timestring.substr (0,4);
std::string sMonth = timestring.substr (4,2);
std::string sDay = timestring.substr (6,2);
std::string sHour = timestring.substr (9,2);
std::string sMinute = timestring.substr (11,2);
std::string sSecond = timestring.substr (13,2);
std::string sUSecond = timestring.substr (16);
istringstream isYear(sYear);
istringstream isMonth(sMonth);
istringstream isDay(sDay);
istringstream isHour(sHour);
istringstream isMinute(sMinute);
istringstream isSec(sSecond);
istringstream isUSec(sUSecond);
// use is like an input stream
int iYear,iMonth,iDay,iHour,iMinute,iSecond,iUSecond;
isYear >> iYear;
isMonth >>iMonth;
isDay >>iDay;
isHour >>iHour;
isMinute >>iMinute;
isSec >>iSecond;
isUSec >>iUSecond;
timeblock.uiYear = iYear;
timeblock.usiMonth = time.wMonth;
timeblock.usiDay = time.wDay;
timeblock.usiHour = time.wHour;
timeblock.usiMinute = time.wMinute;
timeblock.usiSec = time.wSecond;
timeblock.udiUSec = time.wMilliseconds;
// Display version information
}
I've seen this error caused by using a static variable in native code in a C++/CLI assembly.
The only workaround I found was to remove the static variable, e.g., by moving it to class or file scope.
However, if this static variable is in the boost code, doing so may not be easy/possible. In that case, you could create a separate C++ file that's compiled without /clr, use the boost function in that file, and link that into your C++/CLI assembly.
This error seems to be caused by the compiler generating incorrect code. I filed a bug with Microsoft, which was closed "won't fix", but the compiler team gave some other workarounds in their response.
Try using
#pragma managed(push, off)
#pragma managed(pop)
around the #include lines for all boost header files.
I'm on the same problem for a few days now.
this is the best workaround i have found. and also explains why this is happening.
look at the end (number 7 and 9)
hope this helps http://www.codeproject.com/Articles/442784/Best-gotchas-of-Cplusplus-CLI

Resources