⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buffers.h

📁 source of perl for linux application,
💻 H
📖 第 1 页 / 共 2 页
字号:
/* 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 + -