C++ 如何处理C++;Lua中的类构造失败

C++ 如何处理C++;Lua中的类构造失败,c++,class,constructor,lua,swig,C++,Class,Constructor,Lua,Swig,我使用SWIG绑定C++类,这样我就可以在Lua. 我想知道是否可以处理Lua C++类的构造失败。 例如,我有一个Test类,它试图在构建用户数据时获取用户数据 void *getUserdata(lua_State *L, const char *key) { lua_pushstring(L, key); lua_gettable(L, LUA_REGISTRYINDEX); return lua_touserdata(L, -1); } class Test {

我使用SWIG绑定C++类,这样我就可以在Lua. 我想知道是否可以处理Lua C++类的构造失败。 例如,我有一个
Test
类,它试图在构建用户数据时获取用户数据

void *getUserdata(lua_State *L, const char *key)
{
    lua_pushstring(L, key);
    lua_gettable(L, LUA_REGISTRYINDEX);
    return lua_touserdata(L, -1);
}

class Test
{
public:
    Test(lua_State *L)
    :data(static_cast<MyData *>(getUserdata(L, "my_name"))){};

    void setDataNum(int num)
    {
        data->num = num;
    }
private:
       MyData *data;
};
void*getUserdata(lua_State*L,const char*key)
{
lua_推力串(L,键);
lua_gettable(L,lua_注册表索引);
返回lua_-tuserdata(L,-1);
}
课堂测试
{
公众:
测试(lua_状态*L)
:data(static_cast(getUserdata(L,“我的名字”)){};
void setDataNum(int num)
{
数据->数值=数值;
}
私人:
MyData*数据;
};
但是,如果
getUserdata()
返回
nullptr
,调用
setDataNum()
会使我的应用程序崩溃


我想知道是否有任何方法可以检测和处理构造失败(
data
在本例中变成
nullptr
),这样类就不会在Lua中创建。

错误处理的第一步是检查错误。从:

如果给定索引处的值是完整的userdata,则返回其块地址。如果该值是light userdata,则返回其指针。否则,返回
NULL

这意味着我们可以通过检查
data
是否为
NULL
来轻松检查调用是否成功。然后我们可以相应地采取行动,我选择抛出一个异常

测试.hpp

#pragma once
#include <stdexcept>

#include <lua.hpp>

struct MyData {
    int num;
};

void *getUserdata(lua_State *L, const char *key) {
    lua_pushstring(L, key);
    lua_gettable(L, LUA_REGISTRYINDEX);
    return lua_touserdata(L, -1);
}

class Test {
public:
    Test(lua_State *L)
        : data(static_cast<MyData *>(getUserdata(L, "my_name"))) {
        if (data == nullptr) {
            throw std::runtime_error("invalid userdata at \"my_name\"");
        }
    };

    void setDataNum(int num) { data->num = num; }

private:
    MyData *data;
};
%module example
%{
#include "test.hpp"
%}

%include <exception.i>
%exception {
    try {
        $action
    } catch (std::exception const &e) {
        SWIG_exception(SWIG_RuntimeError, e.what());
    }
}

%typemap(default) (lua_State *L) { $1 = L; }
%include "test.hpp"
Lua没有异常,因此没有
try
-
catch
块。相反,Lua的概念是使用
pcall
进行受保护的调用。这将返回调用是否成功以及调用结果或错误的标志

local-example=require(“示例”)
本地成功,c=pcall(示例.Test)
如果(成功)那么
c:setDataNum(1)
其他的
印刷品(c)
结束
调用示例:

$swig-c++-lua test.i
$clang++-Wall-Wextra-Wpedantic-I/usr/include/lua5.2-fPIC-sharedtest\u wrap.cxx-o example.so-llua5.2
$lua5.2 test.lua
SWIG_运行时错误:“我的_名称”处的用户数据无效

在调用由
getUserdata
创建的类之前,您是否可以创建一个lua类,该类允许您检查您首先从lua调用的userData的状态?您说您正在使用SWIG,但您正在直接操作lua堆栈,并且您发布的示例不是SWIG接口文件。我不清楚你在问什么。@HenriMenke很抱歉,我的SWIG接口文件中有以下代码:
%typemap(默认值)(lua_State*L){$1=L;}
这是它如何直接操作lua堆栈的。也许我应该为类
Test
创建一个类型映射来处理异常?既然可以将它们作为
Test
的私有成员保存,为什么还要将它们保存为用户数据?“我的名字”的用户数据中有什么?你有点挫败SWIG的目的,这是为了给C++和脚本语言之间一个干净的边界。我也没能对你的问题投赞成票,我现在投了,这应该会让你超过15个代表。
%module example
%{
#include "test.hpp"
%}

%include <exception.i>
%exception {
    try {
        $action
    } catch (std::exception const &e) {
        SWIG_exception(SWIG_RuntimeError, e.what());
    }
}

%typemap(default) (lua_State *L) { $1 = L; }
%include "test.hpp"