📄 buffers.h
字号:
/* buffers.h -- Version 1.11 *//* The following abbreviations are used at start of parameter names * to indicate the type of data: * s string (char * or WCHAR *) [PV] * sw wide string (WCHAR *) [PV] * p pointer (usually to some structure) [PV] * a array (packed array as in C) (usually of some structure) [PV] * called a "vector" or "vect" in some places. * n generic number [IV, UV, or NV] * iv signed integral value [IV] * u unsigned integral value [UV] * d floating-point number (double) [NV] * b boolean (bool) [IV] * c count of items [UV] * l length (in bytes) [UV] * lw length in WCHARs [UV] * h a handle [IV] * r record (structure) [PV] * sv Perl scalar (s, i, u, d, n, or rv) [SV] * rv Perl reference (usually to scalar) [RV] * hv reference to Perl hash [HV] * av reference to Perl array [AV] * cv Perl code reference [PVCV] * * Unusual combined types: * pp single pointer (to non-Perl data) packed into string [PV] * pap vector of pointers (to non-Perl data) packed into string [PV] * * Whether a parameter is for input data, output data, or both is usually * not reflected by the data type prefix. In cases where this is not * obvious nor reflected in the variable name proper, you can use * the following in front of the data type prefix: * i an input parameter given to API (usually omitted) * o an Output parameter taken from API * io Input given to API then overwritten with Output taken from API *//* Buffer arguments are usually followed by an argument (or two) specifying * their size and/or returning the size of data written. The size can be * measured in bytes ["lSize"] or in characters [for (char *) buffers such as * for *A() routines, these sizes are also called "lSize", but are called * "lwSize" for (WCHAR *) buffers, UNICODE strings, such as for *W() routines]. * * Before calling the actual C function, you must make sure the Perl variable * actually has a big enough buffer allocated, and, if the user didn't want * to specify a buffer size, set the buffer size to be correct. This is what * the grow_*() macros are for. They also handle special meanings of the * buffer size argument [described below]. * * Once the actual C function returns, you must set the Perl variable to know * the size of the written data. This is what the trunc_*() macros are for. * * The size sometimes does and sometimes doesn't include the trailing '\0' * [or L'\0'], so we always add or substract 1 in the appropriate places so * we don't care about this detail. * * A call may 1) request a pointer to the buffer size which means that * the buffer size will be overwritten with the size of the data written; * 2) have an extra argument which is a pointer to the place to write the * size of the written data; 3) provide the size of the written data in * the function's return value; 4) format the data so that the length * can be determined by examining the data [such as with '\0'-terminated * strings]; or 5) write fixed-length data [usually sizeof(STRUCT)]. * This obviously determines what you should use in the trunc_*() macro # to specify the size of the output value. * * The user can pass in an empty list reference, C<[]>, to indicate C<NULL> * for the pointer to the buffer which means that they don't want that data. * * The user can pass in C<[]> or C<0> to indicate that they don't care about * the buffer size [we aren't programming in C here, after all] and just try * to get the data. This will work if either the buffer already alloated for * the SV [scalar value] is large enough to hold the data or the API provides * an easy way to determine the required size [and the XS code uses it]. * * If the user passes in a numeric value for a buffer size, then the XS * code makes sure that the buffer is at least large enough to hold a value * of that size and then passes in how large the buffer is. So the buffer * size passed to the API call is the larger of the size requested by the * user and the size of the buffer aleady allocated to the SV. * * The user can also pass in a string consisting of a leading "=" followed * by digits for a buffer size. This means just use the size specified after * the equals sign, even if the allocated buffer is larger. The XS code will * still allocate a large enough buffer before the first call. * * If the function is nice enough to tell us that a buffer was too small * [usually via ERROR_MORE_DATA] _and_ how large the buffer needs to be, * then the XS code should enlarge the buffer(s) and repeat the call [once]. * This resizing is _not_ done for buffers whose size was specified with a * leading "=". * * Only grow_buf() and perhaps trunc_buf() can be used in a typemap file. * The other macros would be used in the parameter declarations or INPUT: * section [grow_*()], the INIT: section [init_*()], or the OUTPUT: section * [trunc_*()]. * * Buffer arguments should be initialied with C<= NO_INIT> [or C<= NULL;>]. * * See also the F<typemap> file. C<oDWORD>, for example, is for an output- * only parameter of type C<DWORD> and you should simply C<#define> it to be * C<DWORD>. In F<typemap>, C<oDWORD> is treated differently than C<DWORD> * in two ways. * * First, if C<undef> is passed in, a C<DWORD> could generate a warning * when it gets converted to 0 while C<oDWORD> will never generate such a * warning for C<undef>. This first difference doesn't apply if specific * initialization is specified for the variable, as in C<= init_buf_l($var);>. * In particular, the init_*() macros also convert C<undef> to 0 without * ever producing a warning. * * Second, passing in a read-only SV for a C<oDWORD> parameter will generate * a fatal error on output when we try to update the SV. For C<DWORD>, we * won't update a read-only SV since passing in a literal constant for a * buffer size is a useful thing to do even though it prevents us from * returning the size of data written via that SV. Since we should use a * trunc_*() macro to output the actual data, the user should be able to * determine the size of data written based on the size of the scalar we * output anyway. * * This second difference doesn't apply unless the paremter is listed in * the OUTPUT: section without specific output instructions. We define * no macros for outputing buffer length parameters so be careful to use * C<oDWORD> [for example] for them if and only if they are output-only. * * Note that C<oDWORD> is the same as C<DWORD> in that, if a defined value * is passed in, it is used [and can generate a warning if the value is * "not numeric"]. So although C<oDWORD> is for output-only parameters, * we still initialize the C variable before calling the API. This is good * in case the parameter isn't always strictly output-only due to upgrades, * bugs, etc. * * Here is a made-up example that shows several cases: * * # Actual GetDataW() returns length of data written to ioswName, not bool. * bool * GetDataW( ioswName, ilwName, oswText, iolwText, opJunk, opRec, ilRec, olRec ) * WCHAR * ioswName = NO_INIT * DWORD ilwName = NO_INIT * WCHAR * oswText = NO_INIT * DWORD &iolwText = init_buf_l($arg); * void * opJunk = NO_INIT * BYTE * opRec = NO_INIT * DWORD ilRec = init_buf_l($arg); * oDWORD &olRec * PREINIT: * DWORD olwName; * INIT: * grow_buf_lw( ioswName,ST(0), ilwName,ST(1) ); * grow_buf_lw( oswText,ST(2), iolwText,ST(3) ); * grow_buf_typ( opJunk,ST(4),void *, LONG_STRUCT_TYPEDEF ); * grow_buf_l( opRec,ST(5),BYTE *, ilRec,ST(6) ); * CODE: * olwName= GetDataW( ioswName, ilwName, oswText, &iolwText, * (LONG_STRUCT_TYPEDEF *)opJunk, opRec, &iolRec ); * if( 0 == olwName && ERROR_MORE_DATA == GetLastError() * && ( autosize(ST(1)) || autosize(ST(3)) || autosize(ST(6)) ) ) { * if( autosize(ST(1)) ) * grow_buf_lw( ioswName,ST(0), ilwName,ST(1) ); * if( autosize(ST(3)) ) * grow_buf_lw( oswText,ST(2), iolwText,ST(3) ); * if( autosize(ST(6)) ) * grow_buf_l( opRec,ST(5),BYTE *, iolRec,ST(6) ); * olwName= GetDataW( ioswName, ilwName, oswText, &iolwText, * (LONG_STRUCT_TYPEDEF *)opJunk, opRec, &iolRec ); * } * RETVAL= 0 != olwName; * OUTPUT: * RETVAL * ioswName trunc_buf_lw( RETVAL, ioswName,ST(0), olwName ); * oswText trunc_buf_lw( RETVAL, oswText,ST(2), iolwText ); * iolwText * opJunk trunc_buf_typ(RETVAL,opJunk,ST(4),LONG_STRUCT_TYPEDEF); * opRec trunc_buf_l( RETVAL, opRec,ST(5), olRec ); * olRec * * The above example would be more complex and less efficient if we used * C<DWORD * iolwText> in place of C<DWORD &iolwText>. The only possible * advantage would be that C<NULL> would be passed in for C<iolwText> if * _both_ C<$oswText> and C<$iolwText> were specified as C<[]>. The *_pl*() * macros are defined [and C<DWORD *> specified in F<typemap>] so we can * handle those cases but it is usually better to use the *_l*() macros * instead by specifying C<&> instead of C<*>. Using C<&> instead of C<*> * is usually better when dealing with scalars, even if they aren't buffer * sizes. But you must use C<*> if it is important for that parameter to * be able to pass C<NULL> to the underlying API. * * In Win32API::, we try to use C<*> for buffer sizes of optional buffers * and C<&> for buffer sizes of required buffers. * * For parameters that are pointers to things other than buffers or buffer * sizes, we use C<*> for "important" parameters [so that using C<[]> * generates an error rather than fetching the value and just throwing it * away], and for optional parameters [in case specifying C<NULL> is or * becomes important]. Otherwise we use C<&> [for "unimportant" but * required parameters] so the user can specify C<[]> if they don't care * about it. The output handle of an "open" routine is "important". */#ifndef Debug# define Debug(list) /*Nothing*/#endif/*#ifndef CAST *# ifdef __cplusplus *# define CAST(type,expr) static_cast<type>(expr) *# else*/# define CAST(type,expr) (type)(expr)/*# endif *#endif*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -