SUPPORT / SAMPLES & SAS NOTES
 

Support

Sample 32080: Using the PROTO procedure to call C functions from within a DATA step

DetailsCodeOutputDownloadsAboutRate It

Overview

This sample demonstrates a call to C functions from within a SAS® DATA step. The capability to call a C function from within a DATA step provides several benefits:

  • If you already have a function written and compiled in a C module, then you can integrate that module with Base® SAS software without having to rewrite the function in SAS code.
  • You can leverage C libraries that contain functions that are not available in SAS.
  • You have the option of using C instead of SAS to define a function.
  • For certain functions, it might be more efficient to use a C function in place of a SAS function.
  • It provides the ability to integrate your SAS program with C libraries from third-party vendors.

The Full Code tab contains the SAS code that is necessary to execute this sample in SAS. That tab also contains instructions that need to be followed in order for the example to run. There is a file on the Downloads tab that you must download, and there is a root path macro variable that you must specify in order to execute the sample code. The Output tab contains the SAS log output that is generated upon a successful run of the code.

Details

While the SAS code contains brief commentary that describes each step, a more detailed explanation of the code follows.

The code begins with preliminaries. After you download the ranmtnrm.dll file from the Downloads tab, you need to set the ROOT macro variable to the path where you stored the ranmtnrm.dll file. Then, you need to assign the LIB library to the same location to provide a place to store files that will be created later in the example. The ranmtnrm.dll file is a C function library that contains random-number generator functions. Use the SEED macro variable to specify a seed for the random-number generator functions.

%let root=C:\temp; libname lib "&root"; %let seed=1;

Now, you must define the prototypes using the PROTO procedure, as shown in the following SAS code. The prototypes are a SAS syntax form of the function declarations that are contained in the header files for the C functions. They consist of the function names and the parameter types for each function.

proc proto package=lib.Proto_ds.ranmtnrm label="Random Number Generators" stdcall; link "&root\ranmtnrm.dll"; double genrand(void) label="Uniform random number generator"; double ranmtnrm(void) label="Normal random number generator"; void sgenrand(unsigned long seed) label="Initialize seed value"; run;

In this section of code, SAS uses the PACKAGE= option to store the prototypes in a function package within a SAS data set file. Syntax for the PACKAGE= option is as follows:

PACKAGE=library.data_set.function_package
The STDCALL option is also necessary if the Dynamic Link Library (DLL) is compiled using the __STDCALL convention. The LINK statement links SAS to the DLL that contains the C functions. The C functions in ranmtnrm.dll are GENRAND, RANMTNRM, and SGENRAND.

A SAS DATA step calls functions that have been defined using the FCMP procedure, and PROC FCMP can call functions that have been set up using PROC PROTO. However, the DATA step cannot directly call functions that have only been set up using PROC PROTO. Thus, an intermediate step is necessary, as shown in the following SAS code:

proc fcmp inlib =lib.Proto_ds outlib=lib.FCmp_ds.ranmtnrm; subroutine sas_sgenrand(seed); call sgenrand(seed); endsub; function sas_genrand(); x1=genrand(); return(x1); endsub; function sas_ranmtnrm(); x2=ranmtnrm(); return(x2); endsub; quit;

In this intermediate step, wrapper functions are defined using PROC FCMP. The DATA step then calls these wrapper functions, which will in turn call the functions that have been set up using PROC PROTO. It is necessary to wrap all PROTO functions inside FCMP functions because the DATA step does not support C data types. The DATA step only supports double and char data types. PROC FCMP supports all C data types; thus, wrapper functions are used for automated and user-defined conversions of SAS data types to or from C data types.

PROC FCMP uses the INLIB= option to specify the SAS data set that contains the function package in which the prototypes are stored. Syntax for the INLIB= option is as follows:

INLIB=library.data_set

The OUTLIB= option specifies the function package in which to store the wrapper functions. Syntax for the OUTLIB= options is as follows:

OUTLIB=library.data_set.function_package

You can use the CMPLIB= system option in the OPTIONS statement to add the SAS data sets that contain the function packages to the search path.

options cmplib=(lib.Proto_ds lib.FCmp_ds);

SAS uses this search path to locate the functions once they are called from within a DATA step.

You can now call the wrapper functions from within the DATA step code. The functions in this sample return uniformly distributed (GENRAND) and normally distributed (RANMTNRM) random numbers based on the seed that is specified by the SEED macro variable. The following DATA step calls these functions and then prints their returned values to the SAS log. See the Output tab for the results.

data _null_; call sas_sgenrand(&seed); x1 = sas_genrand(); call sas_sgenrand(&seed); x2 = sas_ranmtnrm(); put "--------------------"; put "PROTO Function Calls"; put "--------------------"; put "For seed = &seed"; put "GENRAND returns: " x1; put "RANMTNRM returns: " x2; put "--------------------"; run;

Other Notes and Considerations

  • While this sample is designed for Windows hosts, the technique that is used in this sample still applies to other operating systems that support Base SAS software. To run this sample on another operating system, you need a shared library that is equivalent to the ranmtnrm.dll file but that has been built using that other operating system. In the SAS code, you also need to update the path for the ROOT macro variable and the filename in the LINK statement to reflect the different shared library.
  • Note that you need to use a third-party C compiler in order to compile the C source into a shared library such as ranmtnrm.dll.
  • An alternative approach to calling external C functions from SAS is to use the CALL MODULE routine. An advantage of using PROC PROTO is that it supports types other than doubles and strings. PROC PROTO and PROC FCMP support most C types. For more information on the CALL MODULE routine, see "CALL Module Routine" in SAS® 9.2 Language Reference: Dictionary.

Additional Documentation




These sample files and code examples are provided by SAS Institute Inc. "as is" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and fitness for a particular purpose. Recipients acknowledge and agree that SAS Institute shall not be liable for any damages whatsoever arising out of their use of this material. In addition, SAS Institute will provide no support for the materials contained herein.