Pointers 按RPGLE中的指针分配的内存大小

Pointers 按RPGLE中的指针分配的内存大小,pointers,memory-management,ibm-midrange,rpgle,Pointers,Memory Management,Ibm Midrange,Rpgle,有没有办法通过RPGLE中的指针检索分配的内存大小? 内存是用%ALLOC()bif分配的。我将采用以下方法。构建动态阵列服务程序,该程序包含处理动态阵列所需的子过程。功能如下: CreateArray()-创建动态数组并返回其句柄(可以是指针) ArrayPush(句柄:element)-将元素添加到数组的末尾 ArrayPop(handle)-删除并返回数组中的最后一个元素 ArraySize(句柄)-返回数组中当前的元素数 等等 调用者应该知道元素的大小,但是您可以使用varchar和

有没有办法通过RPGLE中的指针检索分配的内存大小?

内存是用
%ALLOC()
bif分配的。

我将采用以下方法。构建动态阵列服务程序,该程序包含处理动态阵列所需的子过程。功能如下:

  • CreateArray()-创建动态数组并返回其句柄(可以是指针)
  • ArrayPush(句柄:element)-将元素添加到数组的末尾
  • ArrayPop(handle)-删除并返回数组中的最后一个元素
  • ArraySize(句柄)-返回数组中当前的元素数
  • 等等
调用者应该知道元素的大小,但是您可以使用
varchar
options(*variable)
来允许子过程确定要加载的元素的长度,或者如果您要加载数据结构,您可以使用
opdesc
。指定“opdesc”对调用方来说是完全透明的,它将在原型中指定,因此调用方甚至不必知道它。然后,子过程可以使用系统API查询操作描述符。我相信这是一个CEEAPI,你可以查一下。要保存阵列,可以使用用户空间。它们的优点是,当空间已满时,您不必重新分配空间,它会自动扩展到16Mb

或者,您可以使用指向用户空间的指针错误来支持基于的数组。泰德·霍尔特在这里有你想要的例子

下面是我创建自动扩展用户空间并返回指向它的指针的子过程

   // Standard Error Code Format
   dcl-ds ErrorCdType1_t   Qualified Template Inz;
     BytesProv             Int(10)   Inz(%size(ErrorCdType1_t));
     BytesAvail            Int(10);
     MsgId                 Char(7);
     Data                  Char(1024) Pos(17);
   end-ds;

   // Qualified Name
   dcl-s Name_t            Char(10) Template Inz('');
   dcl-ds QualName_t       Qualified Template Inz;
     Name                  Like(Name_t) Inz('');
     Lib                   Like(Name_t) Inz('*LIBL');
   end-ds;

   // =====================================================================
   // User Space APIs
   // =====================================================================

   // Create User Space
   dcl-pr CreateUs;
     UserSpace             LikeDs(QualName_t) Const;
     Description           Char(50) Const;
     ReturnPtr             Pointer;
     ErrorCd               LikeDs(ErrorCdType1_t)
                           Options(*NoPass);
   end-pr;
   dcl-pr quscrtus     ExtPgm('QUSCRTUS');
     UserSpace             LikeDs(QualName_t) Const;
     ExtAttribute          Char(10)  Const;
     InitialSize           Int(10)   Const;
     InitialValue          Char(1)   Const;
     PublicAuthority       Char(10)  Const;
     TextDescription       Char(50)  Const;
     Replace               Char(10)  Const  Options(*NoPass);
     ErrorCd               LikeDs(ErrorCdType1_t)
                           Options(*NoPass);
     Domain                Char(10)  Const  Options(*NoPass);
     XferSizeReq           Int(10)   Const  Options(*NoPass);
     OptimumSpaceAlign     Char(1)   Const  Options(*NoPass);
   end-pr;

   // Return Pointer to User Space
   dcl-pr qusptrus     ExtPgm('QUSPTRUS');
     UserSpace             LikeDs(QualName_t) Const;
     ReturnPtr             Pointer;
     ErrorCd               LikeDs(ErrorCdType1_t)
                           Options(*NoPass);
   end-pr;

   // Change User Space Attributes
   dcl-pr quscusat     ExtPgm('QUSCUSAT');
     ReturnedLib           Char(10);
     UserSpace             LikeDs(QualName_t) Const;
     Attribs               LikeDs(us_Attributes_t) Const;
     Error                 LikeDs(ErrorCdType1_t);
   end-pr;

   // ----- Data Structures -------
   dcl-ds us_VariableLengthRec_t   Qualified Template Inz;
     key              Int(10) Inz(0);
     datalen          Int(10) Inz(0);
     data             Int(10);
     charData         Char(1) Overlay(data);
   end-ds;

   dcl-ds us_Attributes_t   Qualified Template Inz;
     numRec           Int(10) Inz(0);
     vlRecs           LikeDs(us_VariableLengthRec_t) Dim(5)
                      Inz(*LikeDs);
   end-ds;

   // ----- Constants -------------
   // Variable Length Record Key
   dcl-c USATR_AUTO_EXTEND       3;   // data Char(1) *On or *Off

   // -----------------------------
   // Create an automatically extendable user space
   // -----------------------------
   dcl-proc CreateUs Export;
     dcl-pi *n;
       UserSpace             LikeDs(QualName_t) Const;
       Description           Char(50) Const;
       ReturnPtr             Pointer;
       ErrorCd               LikeDs(ErrorCdType1_t)
                             Options(*NoPass);
     end-pi;

     dcl-ds ercd      LikeDs(ErrorCdType1_t)  Inz(*LikeDs);
     dcl-ds usatr     LikeDs(us_Attributes_t) Inz(*LikeDs);
     dcl-ds MsgFile   LikeDs(QualName_t)      Inz(*LikeDs);

     dcl-s Lib        Char(10) Inz('');

     if %parms() >= %parmnum(ErrorCd);
       ercd = ErrorCd;
     endif;

     // Create User Space
     quscrtus(UserSpace: '': 8192: x'00': '*EXCLUDE': Description:
              '*NO': ercd);
     if ercd.msgid <> '';
       exsr CheckErcd;
       return;
     endif;

     // Retrieve a pointer to the space
     qusptrus(UserSpace: ReturnPtr: ercd);
     if ercd.msgid <> '';
       exsr CheckErcd;
       return;
     endif;

     // Make Space automatically extendable
     usatr.numrec = 1;
     usatr.vlrecs(1).key = USATR_AUTO_EXTEND;
     usatr.vlrecs(1).datalen = 1;
     usatr.vlrecs(1).chardata = *On;
     quscusat(Lib: UserSpace: usatr: ercd);
     if ercd.msgid <> '';
       exsr CheckErcd;
       return;
     endif;

     // ===========================
     begsr CheckErcd;
       if %parms() >= %parmnum(ErrorCd);
         ErrorCd = ercd;
         return;
       else;
         // Send an escape message if you want to here
       endif;
     endsr;
   end-proc;
您可以这样使用用户空间:

dcl-ds dynArray     Qualified Dim(32767) Based(pArray);
  dsField1          Char(10);
  dsField2          Char(10);
  ...
end-ds;
dcl-s pArray        Pointer Inz(*null);

// Create the user space
pArray = pHandle;

现在,您可以将元素添加到您的hearts内容中,最多可添加32767个元素。如果需要,可以将数组的维度定义为更大。使用这种技术,您的数组不是真正的动态数组,它实际上有32767个元素。但是存储不在程序堆上,而是在QTEMP中的永久用户空间对象中。要使其真正动态化,您必须编写上述服务程序。这不是一项艰巨的任务,但也不是微不足道的。也许这是一个即将发生的开源项目。

我将采用以下方法。构建动态阵列服务程序,该程序包含处理动态阵列所需的子过程。功能如下:

  • CreateArray()-创建动态数组并返回其句柄(可以是指针)
  • ArrayPush(句柄:element)-将元素添加到数组的末尾
  • ArrayPop(handle)-删除并返回数组中的最后一个元素
  • ArraySize(句柄)-返回数组中当前的元素数
  • 等等
调用者应该知道元素的大小,但是您可以使用
varchar
options(*variable)
来允许子过程确定要加载的元素的长度,或者如果您要加载数据结构,您可以使用
opdesc
。指定“opdesc”对调用方来说是完全透明的,它将在原型中指定,因此调用方甚至不必知道它。然后,子过程可以使用系统API查询操作描述符。我相信这是一个CEEAPI,你可以查一下。要保存阵列,可以使用用户空间。它们的优点是,当空间已满时,您不必重新分配空间,它会自动扩展到16Mb

或者,您可以使用指向用户空间的指针错误来支持基于的数组。泰德·霍尔特在这里有你想要的例子

下面是我创建自动扩展用户空间并返回指向它的指针的子过程

   // Standard Error Code Format
   dcl-ds ErrorCdType1_t   Qualified Template Inz;
     BytesProv             Int(10)   Inz(%size(ErrorCdType1_t));
     BytesAvail            Int(10);
     MsgId                 Char(7);
     Data                  Char(1024) Pos(17);
   end-ds;

   // Qualified Name
   dcl-s Name_t            Char(10) Template Inz('');
   dcl-ds QualName_t       Qualified Template Inz;
     Name                  Like(Name_t) Inz('');
     Lib                   Like(Name_t) Inz('*LIBL');
   end-ds;

   // =====================================================================
   // User Space APIs
   // =====================================================================

   // Create User Space
   dcl-pr CreateUs;
     UserSpace             LikeDs(QualName_t) Const;
     Description           Char(50) Const;
     ReturnPtr             Pointer;
     ErrorCd               LikeDs(ErrorCdType1_t)
                           Options(*NoPass);
   end-pr;
   dcl-pr quscrtus     ExtPgm('QUSCRTUS');
     UserSpace             LikeDs(QualName_t) Const;
     ExtAttribute          Char(10)  Const;
     InitialSize           Int(10)   Const;
     InitialValue          Char(1)   Const;
     PublicAuthority       Char(10)  Const;
     TextDescription       Char(50)  Const;
     Replace               Char(10)  Const  Options(*NoPass);
     ErrorCd               LikeDs(ErrorCdType1_t)
                           Options(*NoPass);
     Domain                Char(10)  Const  Options(*NoPass);
     XferSizeReq           Int(10)   Const  Options(*NoPass);
     OptimumSpaceAlign     Char(1)   Const  Options(*NoPass);
   end-pr;

   // Return Pointer to User Space
   dcl-pr qusptrus     ExtPgm('QUSPTRUS');
     UserSpace             LikeDs(QualName_t) Const;
     ReturnPtr             Pointer;
     ErrorCd               LikeDs(ErrorCdType1_t)
                           Options(*NoPass);
   end-pr;

   // Change User Space Attributes
   dcl-pr quscusat     ExtPgm('QUSCUSAT');
     ReturnedLib           Char(10);
     UserSpace             LikeDs(QualName_t) Const;
     Attribs               LikeDs(us_Attributes_t) Const;
     Error                 LikeDs(ErrorCdType1_t);
   end-pr;

   // ----- Data Structures -------
   dcl-ds us_VariableLengthRec_t   Qualified Template Inz;
     key              Int(10) Inz(0);
     datalen          Int(10) Inz(0);
     data             Int(10);
     charData         Char(1) Overlay(data);
   end-ds;

   dcl-ds us_Attributes_t   Qualified Template Inz;
     numRec           Int(10) Inz(0);
     vlRecs           LikeDs(us_VariableLengthRec_t) Dim(5)
                      Inz(*LikeDs);
   end-ds;

   // ----- Constants -------------
   // Variable Length Record Key
   dcl-c USATR_AUTO_EXTEND       3;   // data Char(1) *On or *Off

   // -----------------------------
   // Create an automatically extendable user space
   // -----------------------------
   dcl-proc CreateUs Export;
     dcl-pi *n;
       UserSpace             LikeDs(QualName_t) Const;
       Description           Char(50) Const;
       ReturnPtr             Pointer;
       ErrorCd               LikeDs(ErrorCdType1_t)
                             Options(*NoPass);
     end-pi;

     dcl-ds ercd      LikeDs(ErrorCdType1_t)  Inz(*LikeDs);
     dcl-ds usatr     LikeDs(us_Attributes_t) Inz(*LikeDs);
     dcl-ds MsgFile   LikeDs(QualName_t)      Inz(*LikeDs);

     dcl-s Lib        Char(10) Inz('');

     if %parms() >= %parmnum(ErrorCd);
       ercd = ErrorCd;
     endif;

     // Create User Space
     quscrtus(UserSpace: '': 8192: x'00': '*EXCLUDE': Description:
              '*NO': ercd);
     if ercd.msgid <> '';
       exsr CheckErcd;
       return;
     endif;

     // Retrieve a pointer to the space
     qusptrus(UserSpace: ReturnPtr: ercd);
     if ercd.msgid <> '';
       exsr CheckErcd;
       return;
     endif;

     // Make Space automatically extendable
     usatr.numrec = 1;
     usatr.vlrecs(1).key = USATR_AUTO_EXTEND;
     usatr.vlrecs(1).datalen = 1;
     usatr.vlrecs(1).chardata = *On;
     quscusat(Lib: UserSpace: usatr: ercd);
     if ercd.msgid <> '';
       exsr CheckErcd;
       return;
     endif;

     // ===========================
     begsr CheckErcd;
       if %parms() >= %parmnum(ErrorCd);
         ErrorCd = ercd;
         return;
       else;
         // Send an escape message if you want to here
       endif;
     endsr;
   end-proc;
您可以这样使用用户空间:

dcl-ds dynArray     Qualified Dim(32767) Based(pArray);
  dsField1          Char(10);
  dsField2          Char(10);
  ...
end-ds;
dcl-s pArray        Pointer Inz(*null);

// Create the user space
pArray = pHandle;

现在,您可以将元素添加到您的hearts内容中,最多可添加32767个元素。如果需要,可以将数组的维度定义为更大。使用这种技术,您的数组不是真正的动态数组,它实际上有32767个元素。但是存储不在程序堆上,而是在QTEMP中的永久用户空间对象中。要使其真正动态化,您必须编写上述服务程序。这不是一项艰巨的任务,但也不是微不足道的。也许这是一个即将发生的开源项目。

即使使用MI内置,我也不知道有什么办法。有必要吗?您需要解决什么业务问题?嗨!在主程序中,我正在填充一个数组,定义为基于指针的数组。我这样做是为了避免一个最大维度,因为我不知道会有多少元素。然后,另一个程序调用主程序,将指向数组的指针作为输入传递(以便主程序可以使用它分配内存)。因此,我希望避免传递另一个参数(输出)来标识插入的元素数量,因为我有数组元素的字节大小。如果他们不能做到这一点,用户程序就不太可能做到。再通过一个parm有什么问题?啊。理解(虽然幸运的是,我的职业生涯恰恰相反,鼓励我向前推进,并拖累他人)。如果有必要,可以使用“系统API”点来保护。。。嗯…'不要放弃。40多年前,我在一家价值数十亿美元的跨国DJ40公司工作。上一份工作是在IBM i空间中可能是最大的软件公司,在此之前是在全球最大的PC制造厂担任sys pgmr。一些最小的职位,加上一些地方和州政府工作人员的职位。进步总是有可能的,但不可能。这确实很重要。我不知道有什么办法,即使是MI内置的。有必要吗?您需要解决什么业务问题?嗨!在主程序中,我正在填充一个数组,定义为基于指针的数组。我这样做是为了避免一个最大维度,因为我不知道会有多少元素。然后调用主程序