Reputation: 3145
Using the developement libraries for Lua 5.3.5 and gcc 9.2.0 I have encountered a weird compilation issue for the following minimal snippet:
#include <functional>
extern "C" {
#include "lua.h"
#include "lualib.h"
}
int main()
{
using namespace std::placeholders;
auto lua_simple_call = std::bind(lua_call, _1, 0, 0);
}
gcc complains: error: ‘lua_call’ was not declared in this scope
. This issue does not occur when trying to simply call lua_call
without the use of std::bind
and it also does not seem to occur for other Lua C functions like lua_newtable
etc. I would like to know what's causing this and how to circumvent it.
Upvotes: 3
Views: 80
Reputation: 20141
As OP mentioned, lua_call
is a macro which expands to lua_callk
but this is only half of the truth.
lua_call
is a function macro:
#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
and that makes the difference.
So, lua_call
will expand to lua_callk
only if used with the right number of arguments.
I made an MCVE to demonstrate this:
#include <iostream>
#define lua_call(L, n, r) lua_callk(L, (n), (r))
void lua_callk(void *L, int n, int r)
{
std::cout << "lua_callk(" << L << ", " << n << ", " << r << ")\n";
}
#define TEST(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
TEST(lua_call(nullptr, 2, 1));
//TEST(std::cout << "&lua_call: " << &lua_call << '\n');
}
Output:
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
lua_call(nullptr, 2, 1);
lua_callk(0, 2, 1)
versus:
#include <iostream>
#define lua_call(L, n, r) lua_callk(L, (n), (r))
void lua_callk(void *L, int n, int r)
{
std::cout << "lua_callk(" << L << ", " << n << ", " << r << ")\n";
}
#define TEST(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
TEST(lua_call(nullptr, 2, 1));
std::cout << "&lua_call: " << &lua_call << '\n');
}
Output:
main.cpp: In function 'int main()':
main.cpp:15:34: error: 'lua_call' was not declared in this scope
15 | std::cout << "&lua_call: " << &lua_call << '\n';
| ^~~~~~~~
or, to make this even more obvious:
//#include <iostream>
#define lua_call(L, n, r) lua_callk(L, (n), (r))
void lua_callk(void *L, int n, int r)
{
std::cout << "lua_callk(" << L << ", " << n << ", " << r << ")\n";
}
#define TEST(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
TEST(lua_call(nullptr, 2, 1));
std::cout << "&lua_call: " << &lua_call << '\n';
}
with pre-processor-only run:
# 1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cpp"
void lua_callk(void *L, int n, int r)
{
std::cout << "lua_callk(" << L << ", " << n << ", " << r << ")\n";
}
int main()
{
std::cout << "lua_call(nullptr, 2, 1)" << ";\n"; lua_callk(nullptr, (2), (1));
std::cout << "&lua_call: " << &lua_call << '\n';
}
The fix is obvious as well (as already mentioned in Rafix' comment):
Just wrap lua_bind()
into something addressable: a function or lambda.
Upvotes: 7