我正在实现一个简单的LUA在线解释器,它从纯文本(即C字符串)中获取多个LUA脚本并运行它们.一切正常,但现在我正在测试我的程序的响应,当这些脚本发生语法或运行时错误.
到目前为止,当发生错误时,在调用后lua_pcall我从栈中收到消息错误,如下所示:
[string "..."]:7: attempt to call field 'push' (a nil value)
Run Code Online (Sandbox Code Playgroud)
现在,我想要的是LUA的运行时用[string "..."]虚拟文件名替换令牌(记住解释器从字符串中获取LUA代码),这样如果用户使用名称"my.lua"提交虚拟脚本,那么错误消息从LUA的运行时为该脚本引发的格式为:
my.lua:7: attempt to call field 'push' (a nil value)
Run Code Online (Sandbox Code Playgroud)
我试图分析LUA的源代码,以了解LUA解释器如何成功实现此目的.到目前为止,我发现的是,lua_loadstring()并且lua_loadfile()不同之处在于后者将"@"前面的文件名称推入堆栈.来自LUA的源代码(lauxlib.c):
LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
const char *mode) {
LoadF lf;
int status, readstatus;
int c;
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
if (filename == NULL) {
lua_pushliteral(L, "=stdin");
lf.f = stdin;
}
else { …Run Code Online (Sandbox Code Playgroud) 我一直在使用 Python 3.3 C-API,看看是否可以在计划中的即将进行的项目中使用它,但几乎立即遇到了问题。
即使是这么简单的代码也会崩溃并返回 0xc0000005:
#include <Python.h>
#include <cstdio>
int main(){
Py_Initialize();
Py_IncRef(Py_True); //just in case?
PyObject_Print(Py_True,stdout,Py_PRINT_RAW);
Py_DecRef(Py_True);
Py_Finalize();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
测试显示 PyObject_Print 正在生成崩溃。这段代码和/或我的设置有什么问题?
我是python的新手,但是有一个使用uvloop的异步python应用程序,它使用我创建的C api模块,它也需要访问异步循环.
1)asyncio还没有这个c-api?任何在C中使用事件循环的hack?这是在哪里讨论?
2)uvloop使用我在C中熟悉的libuv.如果我可以抓取uv_loop_t指针,我可以挂钩循环.我想我可以:
A)使用PyObject*到uvloop的循环计算uv_loop_t*的偏移并使用它?假设我知道PyObject_HEAD的长度?
libuv_loop = (uv_loop_t*)((void*)(loop)+0x8);
struct __pyx_obj_6uvloop_4loop_Loop {
PyObject_HEAD
uv_loop_t *uvloop;
Run Code Online (Sandbox Code Playgroud)
B)或非hacky修改uvloop以暴露循环指针.因为我从来没有看过cython代码,所以我完全无能为力.我可以在循环上创建一个python函数,从我的C代码调用它并获取C指针吗?喜欢:
(uv_loop_t*)PyObject_CallFunctionObjArgs( getLoop, NULL )
Run Code Online (Sandbox Code Playgroud)
通过在这里添加getLoop:
https://github.com/MagicStack/uvloop/blob/master/uvloop/loop.pyx
cdef uv.uv_loop_t* _getLoop(self):
return self.uvloop
Run Code Online (Sandbox Code Playgroud) 我无法从加载了 C_API 的 tensorflow 2.0 SavedModel 运行推理,因为我无法按名称访问输入和输出操作。
我通过 TF_LoadSessionFromSavedModel(...) 成功加载了会话:
#include <tensorflow/c/c_api>
...
TF_Status* status = TF_NewStatus();
TF_Graph* graph = TF_NewGraph();
TF_Buffer* r_opts = TF_NewBufferFromString("",0);
TF_Buffer* meta_g = TF_NewBuffer();
TF_SessionOptions* opts = TF_NewSessionOptions();
const char* tags[] = {"serve"};
TF_Session* session = TF_LoadSessionFromSavedModel(opts, r_opts, "saved_model/tf2_model", tags, 1, graph, meta_g, status);
if ( TF_GetCode(status) != TF_OK ) exit(-1); //does not happen
Run Code Online (Sandbox Code Playgroud)
但是,尝试使用以下方法设置输入和输出张量时出现错误:
TF_Operation* inputOp = TF_GraphOperationByName(graph, "input"); //works with "serving_default_input"
TF_Operation* outputOp = TF_GraphOperationByName(graph, "prediction"); //does not work
Run Code Online (Sandbox Code Playgroud)
我作为参数传递的名称被分配给保存模型的输入和输出 keras 层,但不在加载的graph …
我在C++中使用python的C API(2.7)将python树结构转换为C++树.代码如下:
python树以递归方式实现为具有子列表的类.叶节点只是原始整数(不是类实例)
我加载模块并从C++调用蟒方法,使用从代码这里,它返回树,python_tree的一个实例,作为一个++中的PyObject℃.
递归遍历获得的PyObject.要获得孩子的名单,我这样做:
PyObject* attr = PyString_FromString("children");
PyObject* list = PyObject_GetAttr(python_tree,attr);
for (int i=0; i<PyList_Size(list); i++) {
PyObject* child = PyList_GetItem(list,i);
...
Run Code Online (Sandbox Code Playgroud)非常简单,它可以工作,直到我最终遇到分段错误,调用PyObject_GetAttr(Objects/object.c:1193,但我看不到API代码).它似乎发生在访问树的最后一个叶节点上.
我很难确定问题所在.使用C API进行递归是否有任何特殊注意事项?我不确定我是否需要使用Py_INCREF/Py_DECREF,或者使用这些函数.我并不完全理解API的工作原理.任何帮助深表感谢!
编辑:一些最小的代码:
void VisitTree(PyObject* py_tree) throw (Python_exception)
{
PyObject* attr = PyString_FromString("children");
if (PyObject_HasAttr(py_tree, attr)) // segfault on last visit
{
PyObject* list = PyObject_GetAttr(py_tree,attr);
if (list)
{
int size = PyList_Size(list);
for (int i=0; i<size; i++)
{
PyObject* py_child = PyList_GetItem(list,i);
PyObject *cls = PyString_FromString("ExpressionTree");
// check …Run Code Online (Sandbox Code Playgroud) 我在使用MacOS High Sierra上的Python3.6 anaconda发行版处理传递给Python C API包装函数的int列表时遇到问题.我想将传入的int列表转换为我可以在C中使用的int数组.
这里有一个类似的问题使用Python/C API将Python列表传递给C函数,我可以开始工作,但处理一个int列表似乎是不同的.
这是我到目前为止所拥有的.
static PyObject * myModule_sumIt(PyObject *self, PyObject *args) {
PyObject *lst;
if(!PyArg_ParseTuple(args, "O", &lst)) {
Py_DECREF(lst);
return NULL;
}
int n = PyObject_Length(lst);
printf("\nLength of list passed in is %d\n", n);
int nums[n];
int sum = 0;
for (int i = 0; i < n; i++) {
PyLongObject *item = PyList_GetItem(lst, i);
sum += item;
printf("\ni = %d\titem = %d\tsum = %d\n", i, item, sum);
Py_DECREF(item);
}
Py_DECREF(lst); …Run Code Online (Sandbox Code Playgroud) 我为C ++类实现了C-API,该类使用其他对象的共享指针来访问它们。在我的C-API中,我当然只能获得原始指针。因此,我将C-API中的原始指针“转换”为共享指针,然后将其与C ++类方法一起使用:
method(std::shared_ptr<dataType>(raw-pointer));
Run Code Online (Sandbox Code Playgroud)
现在,我遇到的问题是,在“方法”的末尾,总是会调用共享指针析构函数,并且不幸的是,它杀死了我的原始指针指向的对象(我不想要)。因此,如何防止原始指针被杀死?
我已经尝试过像reset()或swap()这样的共享指针功能,但是它们都没有让我的原始指针走...
method(std::shared_ptr<dataType>(raw-pointer));
Run Code Online (Sandbox Code Playgroud)
预期的结果是,此函数返回后,原始指针e仍指向有效对象。实际上,原始指针然后指向已删除的对象。
c-api ×7
c ×3
python ×3
c++ ×2
cython ×1
lua ×1
python-3.x ×1
raw-pointer ×1
recursion ×1
shared-ptr ×1
tensorflow ×1
uvloop ×1