Please enable JavaScript to view this site.

A-Shell Reference

Navigation: Subroutines > DYNLIB

DYNLIB Indirect Output

Scroll Prev Top Next More

Although ASB doesn't normally allow direct handling of pointers, sometimes it is necessary in order to interface with external library routines written in lower-level languages such as C. A case in point occurs when the external routine passes back a pointer to an output string, rather than the contents of the string directly. DYNLIB offers two special parameter codes (capital P and >) plus a special opcode (DCOP_DEREF) to help manage these situations.

In this first example, we want to use DYNLIB to call the following C function which returns a string. But rather than returning it directly, it returns a pointer to the string in the output parameter pstring :

void getstring(char **pstring);

To capture the string data (rather than its pointer), use the parameter code > as follows:

map1 buffer,s,0            ! (dynamic ok, or size sufficient for output)

dlctl.opcode = DCOP_CALL

xcall DYNLIB, dlctl, "getstring(>)v", buffer

 

The ">" parameter code causes DYNLIB to copy the actual output string to the buffer parameter rather than copying its address.

The DCOP_DEREF opcode provides an alternate way to handle pointers passed back by the external library routine. Rather than converting the pointer directly to its value as in the example above using the > parameter code, we instead allow the routine to just pass us back raw pointers (parameter code lower case p), and then use a separate operation (opcode DCOP_DEREF) to copy the strings referenced by the returned pointers into string variables.

To illustrate using the same getstring() function as before, change the parameter type from > to code p (lower case), allowing us to retrieve the address of the string rather than it's contents...

map1 buffer,s,0

map2 address,b,4    ! 32 bit!! (see note below)

 

dlctl.opcode = DCOP_CALL

xcall DYNLIB, dlctl, "getstring(p)v", address   ! get ptr into address

 

Since we can't access the string via its address directly in ASB, we then use the DCOP_DEREF opcode to copy the referenced string into a string variable...

dlctl.opcode = DCOP_DEREF

xcall DYNLIB, dlctl, address, buffer  ! copy string pointed to by address into buffer

Note that the variable you supply to receive the address must match the pointer size for the current execution environment. The example above uses B,4 for a 32 bit environment.  For 64 bit, use X,8.

This two-step method is obviously more complicated than the one-step conversion using code >,  but is the only way to deal with cases where the external routine returns a structure containing string pointers within it.  In such cases, you have to use the generic lower case p to receive the raw structure into a properly mapped ASB structure and then convert the string pointer(s) using individual DCOP_DEREF calls.

Warning: referencing pointers is inherently dangerous—one reason why they are normally out of reach in higher level languages like ASB. Extreme caution must be exercised to make sure that the signature and received parameters match the external library requirements; any discrepancy will likely cause a segmentation fault.

History

2017 November, A-Shell 6.5.1621:  Added parameter type ">" and opcode DCOP_DEREF.