GCC ignores calling convention attribute - gcc

does anyone know why this doesnt work?
void test() [[stdcall]] {
std::cout << "Hello World" << std::endl;
}
when I try to compile with C++11 dialect it says:
"warning: 'stdcall' attribute directive ignored [-Wattributes]"
Why is that? I have a function that really needs to have the stdcall calling convention. The default calling convention in GCC is cdecl. Any suggestions?

The following should work:
#include <iostream>
[[gnu::stdcall]]
void test()
{
std::cout << "Hello World" << std::endl;
}
or you can use the old syntax __attribute__((stdcall)). Compiling with g++ -std=c++11 -m32 I get no warning.

Related

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

How do I link to a library with g++?

I'm trying to compile a little test program with Open ALPR as described on https://github.com/openalpr/openalpr/wiki/Integrating-OpenALPR.
I've come up with something like:
#include <alpr.h>
#include <iostream>
int main (void)
{
alpr::Alpr openalpr("us", "/etc/openalpr/openalpr.conf");
std::cout << "Hello World!" << std::endl;
return 0;
}
but I am unable to get it to compile. I've tried:
g++ -Wall -l /usr/lib/libopenalpr.so test.cpp -o test but I get
/usr/bin/ld: cannot find -l/usr/lib/libopenalpr.so.
/usr/lib/libopenalpr.so does exist and links to libopenalpr.so.2, which also exists. What is the correct way to link to this library?
The answer can be found here:
unable to compile with library

Expanding a lambda for each parameter of a parameter pack: Clang vs. GCC

This code works fine in Clang 3.5:
#include <iostream>
#include <string>
void callFuncs() {}
template<typename Func, typename ...Funcs>
void callFuncs(const Func &func, const Funcs &...funcs)
{
func();
callFuncs(funcs...);
}
template<typename ...Types>
void callPrintFuncs()
{
callFuncs(([] { std::cout << Types() << std::endl; })...);
}
int main()
{
callPrintFuncs<int, float, double, std::string>();
}
However, in GCC 4.9, I get the following error instead:
test.cpp: In lambda function:
test.cpp:16:54: error: parameter packs not expanded with '...':
callFuncs(([] { std::cout << Types() << std::endl; })...);
^
test.cpp:16:54: note: 'Types'
test.cpp: In function 'void callPrintFuncs()':
test.cpp:16:58: error: expansion pattern '<lambda>' contains no argument packs
callFuncs(([] { std::cout << Types() << std::endl; })...);
So, which compiler has a bug, Clang or GCC? The Clang behavior makes the most sense to me at least.
gcc is broken here. There are rules against unexpanded parameter packs in the standard, but the above parameter pack is expanded.
It is expanded after the end of innermost statement it is in, but the standard does not require that the parameter packs be expanded by the end of every statement.
The fact that gcc got it wrong is sort of understandable; naively, you'd think that a parameter pack can only be within one statement, and the failure to expand at the end of the statement is fatal. But lambdas let you nest statements within statements.
A general workaround can be to pass in one lambda and pass in a "tag" type to it.
template<class T>struct tag_t{using type=T;};
template<class Tag>using type_t=typename Tag::type;
template<typename Func, typename ...Ts>
void callOnEachOf(Func&&func, Ts&&...ts)
{
using discard=int[];
(void)discard{0,((void)(
func(std::forward<Ts>(ts))
),0)...};
}
template<typename ...Types>
void callPrintFuncs()
{
callOnEachOf(
[](auto tag){
using Type=type_t<decltype(tag)>;
std::cout << Type() << std::endl;
},
tag_t<Types>...
);
}

SDL2: undefined references to strange functions

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.

Overriding functions from dynamic libraries

Hello I have a program with a global function that I'd like to customize at run time. Say, there are many versions of function foo() scattered over shared libraries. Now, based on system configuration detected at run time I'd like to use function from appropriate library.
File loader.cpp:
#include <dlfcn.h>
#include <iostream>
void __attribute__((weak)) foo();
int main(int argc, char *argv[])
{
void* dl = dlopen("./other.so", RTLD_NOW | RTLD_GLOBAL);
if (!dl)
{
std::cerr << dlerror() << std::endl;
return 1;
}
if (foo)
{
foo();
}
else
{
std::cerr << "No foo?" << std::endl;
}
dlclose(dl);
return 0;
}
File other.cpp:
#include <iostream>
void foo()
{
std::cout << "FOO!" << std::endl;
}
I compile the program with
g++ -Wall -fPIC -o loaded loader.cpp -ldl
g++ -Wall -fPIC -shared -o other.so other.cpp
However the weak symbol is not overriden. Any hints?
Symbols are resolved during load time of the image in which they are referenced. So when your executable is loaded, the reference to foo is already resolved. A later dlopen won't go and rebind all symbols - it only may affect later loads.
You'll have to use dlsym instead, or set LD_PRELOAD:
martin#mira:/tmp$ LD_PRELOAD=/tmp/other.so ./loaded
FOO!
You compiled the shared lib with g++.
As a result, the name of the function is mangled:
$ nm -S other.so |grep foo
0000000000000690 000000000000002e T _Z3foov
If you make it a pure C code and compile with
gcc instead of g++, you'll find it working as you expect.
Alternatively, define it as follows:
extern "C" void foo()
{
std::cout << "FOO!" << std::endl;
}

Resources