寻找一种从辅助函数调用 Perl XS C API 函数/宏的方法

2023-12-19

我一直在尝试 Perl XS C API,但遇到了障碍。

我在下面简化了我的示例。假设现有结构 MyObject 然后访问属性“a”或“b”并为其中之一创建哈希,我可以使用以下代码:

typedef struct {
   const char *prop_a;
   const char *prop_b;
   struct {
    const char **items;
    int num;
   } names;
}   MyObjectInfo;

typedef MyObjectInfo *MyObject;

MODULE = my_obj            PACKAGE = MyObject    PREFIX = my_obj_

SV *
my_obj_a(o)
   MyObject o

   CODE:
   SV *info = newHV();
   hv_store(info, “a”, 1, newSVpvn(o->prop_a, strlen(o->prop_a)), 0);
   int i;
   for(i = 0; i < o->names.num; i++) {
        const char *n = o->names.items[i];
        hv_store(info, n, strlen(n), newSViv(i), 0);
   }
   RETVAL = sv_2mortal(newrv_noinc(val));
 
   OUTPUT:
   RETVAL

SV *
my_obj_b(o)
   MyObject o

   CODE:
   SV *info = newHV();
   hv_store(info, “b”, 1, newSVpvn(o->prop_b, strlen(o->prop_b)), 0);
   int i;
   for(i = 0; i < o->names.num; i++) {
        const char *n = o->names.items[i];
        hv_store(info, n, strlen(n), newSViv(i), 0);
   }
   RETVAL = sv_2mortal(newrv_noinc(val));
 
   OUTPUT:
   RETVAL

我想做的是分享像这样的实用函数中的一些功能

SV *create_obj_hash(MyObjectInfo *o, const char *k, const char *p) {
    SV *val = newHV();
    hv_store(val, k, strlen(k), newSVpvn(p, strlen(p)), 0);
    int i;
    for(i = 0; i < o->names.num; i++) {
        const char *n = o->names.items[i];
        hv_store(info, n, strlen(n), newSViv(i), 0);
    }
    return val;
}

MODULE = my_obj            PACKAGE = MyObject    PREFIX = my_obj_

SV *
my_obj_a(o)
   MyObject o

   CODE:
   SV *info = create_obj_hash(o, “a”, o->prop_a);
   RETVAL = sv_2mortal(newrv_noinc(val));
 
   OUTPUT:
   RETVAL

SV *
my_obj_b(o)
   MyObject o

   CODE:
   SV *info = create_obj_hash(o, “b”, o->prop_b);;
   RETVAL = sv_2mortal(newrv_noinc(val));
 
   OUTPUT:
   RETVAL

但是,当我在 create_obj_hash() 中进行宏扩展时失败,并显示以下消息。

myobj.xs: In function 'create_obj_hash':
/usr/lib/x86_64-linux-gnu/perl/5.28/CORE/perl.h:175:16: error: 'my_perl' undeclared (first use in this function); did you mean 'my_fork'?
 #  define aTHX my_perl
                ^~~~~~~
ppport.h:6145:41: note: in definition of macro 'MUTABLE_PTR'
 #  define MUTABLE_PTR(p) ({ void *_p = (p); _p; })
                                         ^
/usr/lib/x86_64-linux-gnu/perl/5.28/CORE/hv.h:651:17: note: in expansion of macro 'MUTABLE_HV'
 #define newHV() MUTABLE_HV(newSV_type(SVt_PVHV))
                 ^~~~~~~~~~
/usr/lib/x86_64-linux-gnu/perl/5.28/CORE/perl.h:188:18: note: in expansion of macro 'aTHX'
 #  define aTHX_  aTHX,
                  ^~~~
/usr/lib/x86_64-linux-gnu/perl/5.28/CORE/embed.h:532:40: note: in expansion of macro 'aTHX_'
 #define newSV_type(a)  Perl_newSV_type(aTHX_ a)
                                        ^~~~~
/usr/lib/x86_64-linux-gnu/perl/5.28/CORE/hv.h:651:28: note: in expansion of macro 'newSV_type'
 #define newHV() MUTABLE_HV(newSV_type(SVt_PVHV))
                            ^~~~~~~~~~
myobj.xs:42:19: note: in expansion of macro 'newHV'
     return (void*)newHV();

预先非常感谢您, 布莱恩


首先,您可能缺少以下部分或全部内容:

#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

主要问题是您没有提供context到 API 调用。

某些 Perl 版本允许进程同时运行多个解释器实例。如果-Dmultiplicity在创建 Perl 时使用,构建将支持它。 (您可以使用以下命令检查这一点perl -V:usemultiplicity.) -Dmultiplicity隐含于-Dusethreads,构建一个选项perl具有线程支持(因为为每个线程创建解释器的实例)。

因此,大量的 Perl API 调用需要调用者提供context(“THX”)标识要使用的解释器。将解释器视为一个对象(在该词的 OOP 意义上),将上下文视为调用者。

在 XS 代码中,会自动为您创建一个包含上下文的变量。该变量通过使用宏自动传递给 Perl API 调用。

#define newSVpvn(a,b) Perl_newSVpvn(aTHX_ a,b)
//                                  ^^^^^
//                      Causes the context to be passed
//                      to Perl_newSVpvn, the real name
//                      of newSVpvn.

因此,您需要上下文才能完成这项工作(无论是哪一个)newSVpvn and Perl_newSVpvn你用)。要获取上下文,请使用以下宏:

  • If your function has no parameters besides the context,
    • Use pTHX作为函数声明的第一个参数。
    • Use aTHX作为调用函数的第一个参数。
  • If your function has parameters besides the context,
    • Use pTHX_作为函数声明的第一个参数。
    • Use aTHX_作为调用函数的第一个参数。

"p“ 代表“参数”,“a“ 代表“论证”,并且“_" 代表逗号。

在你的情况下,你会使用

STATIC SV *create_obj_hash(pTHX_ MyObjectInfo *o, const char *k, const char *p) {
#define create_obj_hash(a,b,c) create_obj_hash(aTHX_ a,b,c)
    ...
}

感谢#define,您可以继续使用

SV *info = create_obj_hash(o, "b", o->prop_b);

未经测试。如果有任何问题请告诉我。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

寻找一种从辅助函数调用 Perl XS C API 函数/宏的方法 的相关文章

  • Poco c++Net:Http 从响应中获取标头

    我使用 POCO C Net 库进行 http 我想尝试制定持久缓存策略 首先 我认为我需要从缓存标头中获取过期时间 并与缓存值进行交叉检查 如果我错了 请告诉我 那么我如何从中提取缓存头httpResponse 我已经看到你可以用 Jav
  • 一元 +/- 运算符如何可能导致“-a”或“+a”中的整数提升,“a”是算术数据类型常量/变量?

    这句看似微不足道的台词摘自我的迈克 巴纳汉和布雷迪的 C 书 第 2 8 8 2 节 http publications gbdirect co uk c book chapter2 expressions and arithmetic h
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • 增强精神、递归和堆栈溢出

    为什么下面的代码在运行时崩溃 它会给出堆栈溢出错误 include
  • 根据对象变量搜索对象列表

    我有一个对象列表 这些对象具有三个变量 ID 名称和值 这个列表中可能有很多对象 我需要根据ID或Name找到一个对象 并更改值 例子 class objec public string Name public int UID public
  • UI 函数在快速事件完成之前触发

    我有一个停靠在 Silverlight 应用程序中的 Web 浏览器框架 有时会在其上弹出全窗口 XAML Silverlight UI 元素 我已经或多或少修复了一个老问题 即 Web 框架的内容似乎与 Silverlight 内容不能很
  • 如何对 NServiceBus.Configure.WithWeb() 进行单元测试?

    我正在构建一个 WCF 服务 该服务接收外部 IP 上的请求并将其转换为通过 NServiceBus 发送的消息 我的单元测试之一调用Global Application Start 它执行应用程序的配置 然后尝试将 Web 服务解析为 验
  • 如何在三个 IEnumerable 上使用 Zip [重复]

    这个问题在这里已经有答案了 可能的重复 使用 Linq 从 3 个集合创建项目 https stackoverflow com questions 5284315 create items from 3 collections using
  • 使用具有抗锯齿功能的 C# 更改抗锯齿图像的背景颜色

    我有一个图像需要更改背景颜色 例如 将下面示例图像的背景更改为蓝色 然而 图像是抗锯齿的 所以我不能简单地用不同的颜色替换背景颜色 我尝试过的一种方法是创建第二个图像 仅作为背景 并更改其颜色并将两个图像合并为一个图像 但是这不起作用 因为
  • 如何使用 NPOI 按地址(A1、A2)获取 Excel 单元格值

    我有一个 Excel 单元格地址 例如 A1 A2 如何使用 C 中的 NPOI 框架以编程方式访问此单元格 我找到的一些 Java POI 示例代码 CellReference cr new CellReference A1 row my
  • 从BackgroundWorker线程更新图像UI属性

    在我正在编写的 WPF 应用程序中 我有一个 TransformedBitmap 属性 该属性绑定到 UI 上的 Image 对象 每当我更改此属性时 图像就会更新 因此显示在屏幕上的图像也会更新 为了防止在检索下一张图像时 UI 冻结或变
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • 逆向工程 ASP.NET Web 应用程序

    我有一个 ASP NET Web 应用程序 我没有源代码 该 bin 包含 10 个程序集和一个 compiled 文件 我在 App Code dll 上使用 Reflector 它向我显示了类和命名空间之类的东西 但它太混乱了 有没有什
  • 如何停止无限循环?

    我正在编写一个程序 该程序将计算三角形或正方形的面积 然后提示用户是否希望计算另一个 我的代码已经运行到可以计算任一形状的面积的程度 但随后不再继续执行代码的其余部分 例如 如果选择了正方形 则计算面积 然后返回到正方形边长的提示 我假设这
  • C++ 中 void(*)() 和 void(&)() 之间的区别[重复]

    这个问题在这里已经有答案了 在此示例代码中 func1是类型void int double and funky是类型void int double include
  • 如何得知客户端从服务器的下载速度?

    根据客户的下载速度 我想以低质量或高质量显示视频 任何 Javascript 或 C 解决方案都是可以接受的 Thanks 没有任何办法可以确定 您只能测量向客户端发送数据的速度 如果没有来自客户端的任何类型的输入来表明其获取信息的速度 您
  • INotifyPropertyChanged 和 propertyName

    我一直不确定它的含义propertyName实施时INotifyPropertyChanged 所以一般来说你实现INotifyPropertyChanged as public class Data INotifyPropertyChan
  • DataContractSerializer 事件/委托字段问题

    在我的 WPF 应用程序中 我正在使用DataContractSerializer序列化对象 我发现它无法序列化具有事件或委托声明的类型 考虑以下失败的代码 Serializable public abstract class BaseCl
  • 为什么匹配模板类上的部分类模板特化与没有模板匹配的另一个部分特化不明确?

    这个问题可能很难用标题中的句子来描述 但这里有一个最小的例子 include

随机推荐