How to bind member function with std::function? - c++11

I want to bind member function, but it seems failed.
Q4kDeviceSource.hh
class Q4kDeviceSource {
public:
void videoStreamCallback(QIPCamStreamCbType streamCbType, uint32_t streamId, uint8_t *buffer, size_t bufferSize);
。。。
}
typedef std::function<void(QIPCamStreamCbType cbType, uint32_t streamId,
uint8_t* buffer, size_t bufferSize)>
StreamCallback;
Q4kDeviceSource.cpp
。。。
StreamCallback videoElementryCb = std::bind(&Q4kDeviceSource::videoStreamCallback, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
videoElementryCb(QIPCamStreamCbType::QIPCAM_STREAMCBTYPE_NORMAL,id,NULL,0);
。。。
build failed!
./prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.8/include/functional:2463: error: undefined reference to 'std::__throw_bad_function_call()'
collect2: error: ld returned 1 exit status

Looks like you link with gcc instead of g++.
The difference is that g++ also links in libstdc++, whereas gcc does not.
Either link with g++ or add -lstdc++ to your linker command line.

Related

Error while building a static Linux binary (with musl-libc) that includes LuaJIT

I've cloned the LuaJIT git repo and built it with:
make STATIC_CC="musl-gcc" BUILDMODE="static"
Then, I compiled a simple Lua "hello world" script into a C header file:
luajit -b test.lua test.h
test.h:
#define luaJIT_BC_test_SIZE 52
static const unsigned char luaJIT_BC_test[] = {
27,76,74,2,10,45,2,0,3,0,2,0,4,54,0,0,0,39,2,1,0,66,0,2,1,75,0,1,0,20,72,101,
108,108,111,32,102,114,111,109,32,76,117,97,33,10,112,114,105,110,116,0
};
After that, I wrote a simple C wrapper by following the official example, test.c:
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "test.h"
int main(void) {
int error;
lua_State *L = lua_open();
luaL_openlibs(L);
error = luaL_loadbuffer(L, (const char *) luaJIT_BC_test, luaJIT_BC_test_SIZE, "test") || lua_pcall(L, 0, 0, 0);
if (error) {
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L);
return 0;
}
But when I try to build it, it crashes with an error:
$ musl-gcc -static -ILuaJIT/src -LLuaJIT/src -o test test.c -lluajit
/usr/bin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/libgcc_eh.a(unwind-dw2-fde-dip.o): in function `_Unwind_Find_FDE':
(.text+0x1953): undefined reference to `_dl_find_object'
collect2: error: ld returned 1 exit status
It's related to libgcc, so I tried building everything with musl-clang, but still got the same error. Can someone explain what I'm missing here?
Figured it out - I needed to build LuaJIT with TARGET_XCFLAGS=-DLUAJIT_NO_UNWIND like so:
make STATIC_CC="musl-gcc" BUILDMODE="static" TARGET_XCFLAGS=-DLUAJIT_NO_UNWIND
I guess this just disables C++ exceptions support, but I'm not sure what the real implications are. Seems to work fine, for now.

Fixing warning "Wundefined-var-template"

Searching for duplicates currently gives:
This post which specifically treats the case of a Singleton implementation, and in which the answers avoids the warning altogether with a different implementation.
This post which answers itself without solving the issue.
A suggested duplicate which explains how to implement template member functions (not relevant).
Another suggested duplicate explaining how to define template static members (not relevant).
As far as I understand, none of these answers the question of how to get rid of Wundefined-var-template with clang++ 3.8+ in a situation similar to the MCVE below?
File a.h
#ifndef A_INCLUDED
#define A_INCLUDED
template <class T>
struct A
{
static const char *name;
};
#endif
File a.cpp
#include "a.h"
template <> const char* A<double>::name = "Johnny";
template <> const char* A<float>::name = "Dude";
File b.cpp
#include <cstdio>
#include "a.h"
void say_it() {
printf( "%s\n", A<double>::name );
}
Run from a terminal:
$ clang++ -c -o a.o -std=c++11 a.cpp
$ clang++ -c -o b.o -std=c++11 b.cpp a.o
clang: warning: a.o: 'linker' input unused [-Wunused-command-line-argument]
b.cpp:5:32: warning: instantiation of variable 'A<double>::name' required here, but no definition is available [-Wundefined-var-template]
printf( "%s\n", A<double>::name );
^
./a.h:7:28: note: forward declaration of template entity is here
static const char *name;
^
b.cpp:5:32: note: add an explicit instantiation declaration to suppress this warning if 'A<double>::name' is explicitly instantiated in another translation unit
printf( "%s\n", A<double>::name );
^
1 warning generated.
Demo
Do as warning message explain, add (in a.h):
template <> const char* A<double>::name;
Demo

GCC (minGW - Windows 10) report that there is no reference to symbol defined in .o file when I'm trying to embed the binary into executable

creating .o file
ld -r -b binary -o baked.o baked.txt
λ nm baked.o
0000000f D _binary_baked_txt_end
0000000f A _binary_baked_txt_size
00000000 D _binary_baked_txt_start
Code:
#include <stdlib.h>
#include <stdio.h>
extern char *_binary_baked_txt_end;
extern char _binary_baked_txt_size;
extern char *_binary_baked_txt_start;
int main(void) {
printf("the baked is %s", _binary_baked_txt_start);
return 0;
}
compiling:
λ gcc -o main baked.o main.c
C:\Users\566\AppData\Local\Temp\cc4um6Mn.o:main.c:(.text+0x12): undefined reference to `_binary_baked_txt_start'
collect2.exe: error: ld returned 1 exit status
The question is, what do I do wrong? I see the symbols into .o file, I compile it with main.c file, what could go wrong?
I should use just:
binary_baked_txt_end;
binary_baked_txt_size;
binary_baked_txt_start;
because of the COFF format on Windows machines.
and the right way to do will be:
extern char binary_baked_txt_end[];
extern char binary_baked_txt_size;
extern char binary_baked_txt_start[];
because in that way it's clear that binary_baked_txt_end is a adress that points to a char (in my case) and it will be safer, nobody won't be able to assign new value to it.

go runtime fails to compile

I am just wondering why would go runtime fail to build. How do we pass flags (-fpermissive in this case) to the c compiler which golang compiler is using to build the runtime. I am using gcc-4.6.2 on ubuntu 12.04
../../../thirdparty/go1.4.2/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/src/runtime/cgo/gcc_linux_amd64.c: In function ‘void _cgo_sys_thread_start(ThreadStart*)’:
../../../thirdparty/go1.4.2/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/src/runtime/cgo/gcc_linux_amd64.c:45:41: error: invalid conversion from ‘void*’ to ‘__sigset_t*’ [-fpermissive]
A sample program written also fails to compile, it seems the nil defined in the go code is the problem, i wonder how others are working, when does the golang compiler compiles this runtime code ?
gcc t.c -lpthread -o t
t.c: In function ‘void* hello_world(void*)’:
t.c:12:41: error: invalid conversion from ‘void*’ to ‘__sigset_t*’ [-fpermissive]
/usr/include/x86_64-linux-gnu/bits/sigthread.h:31:12: error: initializing argument 3 of ‘int pthread_sigmask(int, const __sigset_t*, __sigset_t*)’ [-fpermissive]
rk#rk-VirtualBox:~$ gcc -fpermissive t.c -lpthread -o t
t.c: In function ‘void* hello_world(void*)’:
t.c:12:41: warning: invalid conversion from ‘void*’ to ‘__sigset_t*’ [-fpermissive]
rk#rk-VirtualBox:~$ cat t.c
#include<pthread.h>
#include<stdio.h>
#include<signal.h>
#define nil ((void*)0)
static void*
hello_world(void *vptr)
{
sigset_t set;
sigemptyset(&set);
pthread_sigmask(SIG_BLOCK, &set, nil);
printf("hello world");
return NULL;
}
int main(int ac, char **av)
{
pthread_t t;
pthread_create(&t, NULL, hello_world, NULL);
pthread_join(t, NULL);
return 0;
}
/usr/include/x86_64-linux-gnu/bits/sigthread.h:31:12: error: initializing argument 3 of ‘int pthread_sigmask(int, const __sigset_t*, __sigset_t*)’ [-fpermissive]
make: *** [rulemanager] Error 2

Mac OSX ld report 32-bit RIP relative reference out of range error for Absolute symbol

I'm trying to combine objcopy with clang toolchain.
Because objcopy of binutils 2.25 generates broken Mach-O object file, I edit generated object file using my shell script.
$ objcopy-comp.sh -I binary -O mach-o-x86-64 test test.o
$ nm test.o
000000000000000b D _binary_test_end
000000000000000b A _binary_test_size
0000000000000000 D _binary_test_start
However, link against a C code fails with this error message.
$ clang main.c test.o
ld: 32-bit RIP relative reference out of range (-4294971146 max is +/-4GB):
from _main (0x100000EA0) to _binary_test_size (0x0000000B)
in '_main' from main.o for architecture x86_64
(Newlines are inserted for readbility)
Here is main.c.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern const unsigned char binary_test_start[];
extern const unsigned char binary_test_end[];
extern const unsigned char binary_test_size[];
int main(int argc, char *argv[])
{
size_t len = binary_test_end - binary_test_start;
char *data = calloc(len + 1, sizeof(char));
memcpy(data, binary_test_start, len);
data[len] = 0;
printf("%s %ld %d\n", data, len, (int)binary_test_size);
return 0;
}
According to nlist document,
N_ABS (0x2)—The symbol is absolute. The linker does not change the value of an absolute symbol.
but the error message suggests that linker does try to change the value.
How to protect Absolute value from linker?
The Mach-OABI utilizes relative addressing with x86_64. The compiler interprets the address you've used as 32-bit which is out range, nor will it be absolute. Try compiling your code as i386 only and you might have a better chance of success.
Specifically how you're changing the symbol types is unknown since you haven't shown the commands you've used with objcopy.

Resources