zoukankan      html  css  js  c++  java
  • Perl and XS: Example 3: Set::Bit

    #define PERL_NO_GET_CONTEXT
    #include "EXTERN.h"
    #include "perl.h"
    #include "XSUB.h"
    
    #include "ppport.h"
    typedef struct
    {
        /* The range of the set is 0..n_bits - 1 */
        int n_bits;
        /* The number of bytes used for storage. */
        int n_chars;
        /* The bytes used for storage. */
        unsigned char * chars;
    }vector;
    
    typedef vector* Set__Bit;
    
    vector * new (pTHX_ int n_bits)
    {
        vector * p;
        Newx(p,1,vector);
        if (!p) {
    	croak ("Out of memory");
        }
        p->n_bits = n_bits;
    
        /* We use one char to store the bits. The C standard promises that
           one byte contains at least eight bits. */
    
        p->n_chars = (n_bits + 8 - 1) / 8;
    	Newxz(p->chars, p->n_chars, unsigned char);
    
        if (!p->chars) {
    	croak ("Out of memory");
        }
        return p;
    }
    
    /* Set bit "n" in "p". */
    
    void insert (vector *p, int n)
    {
        int q;
        int r;
    
        if (n < 0 || n >= p->n_bits) {
    	croak ("Bit out of range");
        }
    
        q = n / 8;
        r = n % 8;
    
        p->chars[q] |= 1 << r;
    }
    
    void DESTROY (vector *p)
    {
        //printf("good
    ");
        Safefree(p->chars);
        Safefree(p);
    }
    
    
    MODULE = Set::Bit		PACKAGE = Set::Bit		
    
    Set::Bit
    new(package, nBits)
            char *package
            int   nBits
            CODE:
            RETVAL = new(aTHX_ nBits);
            OUTPUT:
            RETVAL
            
    void
    insert(pVector, n)
            Set::Bit pVector
            int      n
    
    
    void
    DESTROY(pVector)
            Set::Bit pVector
    
    #define PERL_NO_GET_CONTEXT
    #include "EXTERN.h"
    #include "perl.h"
    #include "XSUB.h"
    
    #include "ppport.h"
    typedef struct
    {
        /* The range of the set is 0..n_bits - 1 */
        int n_bits;
        /* The number of bytes used for storage. */
        int n_chars;
        /* The bytes used for storage. */
        unsigned char * chars;
    }vector;
    
    typedef vector* Set__Bit;
    
    vector * new (pTHX_ int n_bits)
    {
        vector * p;
        Newx(p,1,vector);
        if (!p) {
    	croak ("Out of memory");
        }
        p->n_bits = n_bits;
    
        /* We use one char to store the bits. The C standard promises that
           one byte contains at least eight bits. */
    
        p->n_chars = (n_bits + 8 - 1) / 8;
    	Newxz(p->chars, p->n_chars, unsigned char);
    
        if (!p->chars) {
    	croak ("Out of memory");
        }
        return p;
    }
    
    /* Set bit "n" in "p". */
    
    void insert (vector *p, int n)
    {
        int q;
        int r;
    
        if (n < 0 || n >= p->n_bits) {
    	croak ("Bit out of range");
        }
    
        q = n / 8;
        r = n % 8;
    
        p->chars[q] |= 1 << r;
    }
    
    void DESTROY (vector *p)
    {
        printf("good luck
    ");
        Safefree(p->chars);
        Safefree(p);
    }
            
    XS(XS_Set__Bit_new)
    {
        dXSARGS;
        if (items != 2)
            croak("Usage: Set::Bit::new(package,nBits)");
        {
            int     	 nBits = (int)SvIV(ST(1));
            Set__Bit 	RETVAL;
    
            RETVAL = new(aTHX_ nBits);
            ST(0) = sv_newmortal();
            sv_setref_pv(ST(0), "Set::Bit", (void*)RETVAL);
        }
        XSRETURN(1);
    }
    
    XS(XS_Set__Bit_insert)
    {
        dXSARGS;
        if (items != 2)
            croak("Usage: Set::Bit::insert(pVector, n)");
        {
            Set__Bit	pVector;
            int     	n = (int)SvIV(ST(1));
    
            if (SvROK(ST(0)) && sv_derived_from(ST(0), "Set::Bit")) {
                pVector = (Set__Bit) SvIV((SV*)SvRV(ST(0)));
            }
            else
                croak("pVector is not of type Set::Bit");
    
            insert(pVector, n);
        }
        XSRETURN_EMPTY;
    }
    
    XS(XS_Set__Bit_DESTROY)
    {
        dXSARGS;
        Set__Bit	pVector;
        if (items != 1)
        {
    		XSRETURN_EMPTY;
        }
    
    	if (SvROK(ST(0))) {
    		IV tmp = SvIV((SV*)SvRV(ST(0)));
    		pVector = INT2PTR(Set__Bit,tmp);
    	}
    	else
    		croak(aTHX_ "%s: %s is not a reference",
    			"Set::Bit::DESTROY",
    			"pVector");
    
    	DESTROY(pVector);
        XSRETURN_EMPTY;
    }
    
    XS_EXTERNAL(boot_Set__Bit)
    {
        dXSARGS;
        const char* file = __FILE__;
    
        newXS("Set::Bit::new", XS_Set__Bit_new, file);
        newXS("Set::Bit::insert", XS_Set__Bit_insert, file);
        newXS("Set::Bit::DESTROY", XS_Set__Bit_DESTROY, file);
    	if (PL_unitcheckav)
    		call_list(PL_scopestack_ix, PL_unitcheckav);
        XSRETURN_YES;
    }
    

    A Perl object

    Earlier, I said that I wanted the Set::Bit object to be the C-languagevector struct, rather than a Perl data object. It didn't work out that way. TheSet::Bit object is indeed a Perl data object: it is the scalar created bysv_setref_pv().

    The Set::Bit object gives the essential features of a C-language object. Data is represented in C, we can write methods in C, and methods written in C access instance data through avector *, passed as the first argument. At the same time, the Set::Bit object gives us the flexibility to write methods in Perl.

    SV = IV(0x1d710a8) at 0x1d710ac
      REFCNT = 1
      FLAGS = (ROK)
      RV = 0x546f14
      SV = PVMG(0x1d67e84) at 0x546f14
        REFCNT = 1
        FLAGS = (OBJECT,IOK,pIOK)
        IV = 30824164                        // 指针p的值
        NV = 0
        PV = 0
        STASH = 0x1d7119c   "Set::Bit"

    上面的SV dump是new方法后的结果,在perl空间中也能够实现同样的效果。比方:

    use Devel::Peek;
    {
    	local $m=30824164;
    	$r = $m;
    	bless $r,"Devel::Peek";
    	
    }
    Dump ($r);

    首先。创建一个暂时的SViv,iv值为指针值(对象指针)

    然后。创建一个RV。并指向之前的这个SV,并在Devel::Peek模块下bless RV

    最后,返回RV。


    输出:

    SV = IV(0x6370b4) at 0x6370b4
      REFCNT = 1
      FLAGS = (ROK)
      RV = 0x4db35c
      SV = PVMG(0x628dd4) at 0x4db35c
        REFCNT = 1
        FLAGS = (OBJECT,IOK,pIOK)
        IV = 30824164
        NV = 0
        PV = 0
        STASH = 0x63733c    "Devel::Peek"



     

  • 相关阅读:
    Winform中TextBox控件开启自动提示补全功能
    使用jsonp进行跨域访问
    sqlite不存在记录则插入数据
    【编译CEF3】编译Chromium(CEF3)源代码增加对mp3/mp4等格式支持的编译手记 完成编译,增加mp3/mp4等格式支持(3) 2018-5-21
    【编译CEF3】编译Chromium(CEF3)源代码增加对mp3/mp4等格式支持的编译手记 编译过程中所遇到的问题(2) 2018-5-20
    【编译CEF3】编译Chromium(CEF3)源代码增加对mp3/mp4等格式支持的编译手记 搭建编译环境的过程中所遇到的问题(1) 2018-5-19
    Git同步本地到Github失败
    Python基础知识总结
    Git命令
    Git仓库创建和文件提交
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/6945321.html
Copyright © 2011-2022 走看看