简体   繁体   English

无法将 Lua 编译为 C++

[英]Can't compile Lua as C++

I'm trying to build Lua 5.4.3 (the latest release as of writing this) using the following CMakeLists.txt (and CMake 3.21) (ignore the fact that the target is called lua_static despite it being a shared lib):我正在尝试使用以下 CMakeLists.txt(和 CMake 3.21)构建 Lua 5.4.3(撰写本文时的最新版本)(忽略目标名为lua_static的事实,尽管它是共享库):

cmake_minimum_required(VERSION 3.16)

project(Lua LANGUAGES CXX)

# make cache variables for install destinations
include(GNUInstallDirs)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

set(LUA_LIB_SRCS 
    "src/ldblib.c"
    "src/ldebug.c"
    "src/ldo.c"
    "src/ldump.c"
    "src/lfunc.c"
    "src/lgc.c"
    "src/linit.c"
    "src/liolib.c"
    "src/lopcodes.c"
    "src/llex.c"
    "src/lmathlib.c"
    "src/lmem.c"
    "src/loadlib.c"
    "src/lobject.c"
    "src/loslib.c"
    "src/lparser.c"
    "src/lstate.c"
    "src/lstring.c"
    "src/lstrlib.c"
    "src/ltable.c"
    "src/ltablib.c"
    "src/ltm.c"
    "src/lundump.c"
    "src/lutf8lib.c"
    "src/lvm.c"
    "src/lzio.c"
    "src/lapi.c"
    "src/lauxlib.c"
    "src/lbaselib.c"
    "src/lcode.c"
    "src/lcorolib.c"
    "src/lctype.c"
)

set(LUA_HEADERS_INSTALL
    "src/lua.h"
    "src/luaconf.h"
    "src/lualib.h"
    "src/lauxlib.h"
    "src/lua.hpp"
)

# Compile directly as C++.
set_source_files_properties(${LUA_LIB_SRCS} PROPERTIES LANGUAGE CXX )

add_library(lua_static SHARED ${LUA_LIB_SRCS})
set_target_properties(lua_static PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(lua_static PROPERTIES DEBUG_POSTFIX d)

# make sure __cplusplus is defined when using msvc
if (MSVC)
    target_compile_options(lua_static PRIVATE /TP       # /TP doesn't is somehow stripped or ignored?
                                       /Zc:__cplusplus)
endif ()

target_include_directories(lua_static
                           PUBLIC
                           "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)

install(TARGETS lua_static
        EXPORT lua_static_targets
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(FILES ${LUA_HEADERS_INSTALL} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

install(EXPORT lua_static_targets
        FILE LuaStaticTargets.cmake
        NAMESPACE lua::
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lua
)

include(CMakePackageConfigHelpers)

configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
  "${CMAKE_CURRENT_BINARY_DIR}/LuaConfig.cmake"
  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lua
)

install(FILES
          "${CMAKE_CURRENT_BINARY_DIR}/LuaConfig.cmake"
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lua
)

When building with MSVC, __cplusplus is defined and therefore I presume everything up until this point is working as intended.使用 MSVC 构建时, __cplusplus已定义,因此我假设__cplusplus一切都按预期工作。 Then after installing, I link against the library like so然后安装后,我像这样链接到库

cmake_minimum_required(VERSION 3.16)
project(TestProject)

add_executable(Test Main.cpp)

# Lua
find_package(lua REQUIRED PATHS ${CMAKE_CURRENT_LIST_DIR}/lua)
set_target_properties(lua::lua_static PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(Test lua::lua_static)

The reason why I want to compile Lua as C++ is to enable exceptions (rather than longjmp ).我想将 Lua 编译为 C++ 的原因是启用异常(而不是longjmp )。 So to test if exceptions would be thrown, I tried invoking one in this test program所以为了测试是否会抛出异常,我尝试在这个测试程序中调用一个

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#include <iostream>

constexpr char* Test_Lua = R"(
function f (x, y)
      unknown()
      return 1/0
en
)";

lua_State* state;

int main(int argc, char* argv[])
{
    state = luaL_newstate();
    luaL_openlibs(state);

    try
    {
        int error = luaL_loadbuffer(state, Test_Lua, strlen(Test_Lua), "Test");
        lua_call(state, 0, LUA_MULTRET); // Should thow, because of the syntax error
    }
    catch (...)
    {
        std::cout << "Exception!" << std::endl;
        goto end;
    }

end:
    lua_close(state);
    return 0;
}

When stepping into lua_call with the debugger, I at some point end up in ldo.c where Visual Studio indicates that LUAI_THROW is not defined via C++ exeption handling.当使用调试器进入lua_call时,我在某个时刻最终进入ldo.c ,其中 Visual Studio 指示LUAI_THROW不是通过 C++ LUAI_THROW处理定义的。 This is because __cplusplus is not defined.这是因为__cplusplus未定义。 Jumping to that source file in my Lua project files created earlier, LUAI_THROW was defined as desired.跳转到我之前创建的 Lua 项目文件中的源文件,根据需要定义了LUAI_THROW The fact that I can include the Lua headers suggests to me that the library has been compiled as a C++ library.我可以包含 Lua 头文件这一事实向我表明该库已被编译为 C++ 库。 In fact if I try to add extern "C" { ... } , I get linker errors.事实上,如果我尝试添加extern "C" { ... } ,我会收到链接器错误。

Can someone shed some light on the cause of the problem?有人可以阐明问题的原因吗?


Edit:编辑:

After looking more into the issue, I realized all compilation as C++ does, is that Lua internally handles functions that return error codes (such as luaL_loadbuffer ) via exceptions.在深入研究这个问题后,我意识到所有编译都像 C++ 一样,是 Lua 在内部处理通过异常返回错误代码的函数(例如luaL_loadbuffer )。 That doesn't mean I get to catch and handle them (which I originally thought).这并不意味着我可以抓住并处理它们(我最初认为)。 Functions like lua_call run in unprotected mode and thus call the panic function (see @bremen_matt's post). lua_call函数在不受保护的模式下运行,因此会调用 panic 函数(参见 @bremen_matt 的帖子)。

I know nothing about Lua.我对 Lua 一无所知。 With that out of the way...有了这个...

I think you are missing something with regards to how Lua is working internally.我认为您在 Lua 内部工作方式方面遗漏了一些东西。 If I modify the macros in ldo.c at about line 57 to read:如果我在第 57 行左右修改ldo.c中的宏以读取:

#include <iostream>
#define LUAI_THROW(L,c) (fprintf(stderr, "THROWING\n"), throw(c))
#define LUAI_TRY(L,c,a) \
    try { a } catch(...) { fprintf(stderr, "CAUGHT\n"); if ((c)->status == 0) (c)->status = -1; }

Then when I run this, I see the output:然后当我运行它时,我看到输出:

THROWING
CAUGHT
PANIC: unprotected error in call to Lua API (attempt to call a string value)

Which suggests that internally Lua is trying to run a snippet of code, catches the exception, and then exits without throwing another exception.这表明 Lua 在内部试图运行一段代码,捕获异常,然后退出而不抛出另一个异常。 Therefore, you as the user cannot catch this exception.因此,您作为用户无法捕获此异常。 It is being consumed inside of Lua.它在 Lua 内部被消耗。

Just a real quick look at the code suggests that maybe you want to use lua_pcall .快速浏览一下代码就会发现您可能想使用lua_pcall It seems that the maybe the p means protected ?似乎p意思是protected and you can do some error handling with that?你可以用它做一些错误处理吗? Either way, that function also does not seem to throw the error higher.无论哪种方式,该函数似乎也不会引发更高的错误。 It seems like you have to pass a function for error handling.似乎您必须传递一个函数来处理错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM