SAS Programming

DATA Step, Macro, Functions and more
BookmarkSubscribeRSS Feed
vioravis
Calcite | Level 5

I am trying to call C++ DLL from SAS and am trying to recreate the example given in the following paper:

http://www.members.cox.net/mhiemstra/C_With_SAS.pdf

I am using Visual C++ Express 2008 (Windows 64 Bit Machine) to build the DLL and I did not get any errors. I place the foolib DLL in system32 folder and tried running the following SAS code. However, I ended up getting an error that Module foolib could not be loaded. Can someone please let me know what is causing this error?? Thank you.

76 DATA _NULL_;

77 InNum = 2;

78 OutNum = MODULEN('*E', 'square', InNum);

79 PUT "******************************";

80 PUT " The input is: " InNum;

81 Put "The square of the input is: " OutNum;

82 PUT "******************************";

83 RUN;

ERROR: Module foolib could not be loaded.

NOTE: Invalid argument to function MODULEN at line 78 column 10.

******************************

The input is: 2

The square of the input is: .

******************************

InNum=2 OutNum=. _ERROR_=1 _N_=1

NOTE: Mathematical operations could not be performed at the following places. The results of the

operations have been set to missing values.

Each place is given by: (Number of times) at (Line):(Column).

1 at 78:10

NOTE: DATA statement used (Total process time):

real time 0.01 seconds

cpu time 0.01 seconds

 

84 QUIT;

7 REPLIES 7
FriedEgg
SAS Employee

Did you build the attribute table in SAS for the function so that it knows how to work with the C routine?

In the document you linked see step 1...

vioravis
Calcite | Level 5

FriedEgg,

Both the attribute table definition and the C function have been taken out of the same paper. They are in pages 4 and 6 respectively. Could you please elaborate on your statement??  Thank you.

vioravis
Calcite | Level 5

I have posted the C function defined below and the corresponding SAS code. Thank you.

/* foolib.c */

#include <windows.h>

BOOL APIENTRY DllMain( HANDLE hModule,

DWORD ul_reason_for_call,

LPVOID lpReserved ) { return TRUE; }

double __stdcall square(double d) { return d*d; }

*****************************************************************************************;

/* foolib.def */

LIBRARY FooLib

DESCRIPTION 'Sample Library Function'

EXETYPE WINDOWS

EXPORTS

square

FILENAME SASCBTBL "work.temp.attrfile.source"; /* PC */

/* FILENAME SASCBTBL "sascbtbl.dat"; */ /* Unix */

DATA _NULL_;

FILE SASCBTBL;

INPUT;

PUT _INFILE_;

CARDS4;

ROUTINE square

MINARG = 1

MAXARG = 1

STACKPOP = CALLED

MODULE = foolib

RETURNS = DOUBLE;

ARG 1 NUM BYVALUE FORMAT=RB8.;

;;;;

RUN;

DATA _NULL_;

InNum = 2;

OutNum = MODULEN('*E', 'square', InNum);

PUT "******************************";

PUT " The input is: " InNum;

Put "The square of the input is: " OutNum;

PUT "******************************";

RUN;

QUIT;

FriedEgg
SAS Employee

Did you check that the function is working properly itself?

C:\WINDOWS\System32\rundll32.exe <dllname>,<entrypoint> <optional arguments>

Also, try replacing '*E' with '*I' for possibly better debug information.

You may also need to register the dll.  See the regsvr32 command in windows command prompt.

chrwag
Calcite | Level 5

I am stuck at the same problem at the moment.

It works fine with the first example on this page (http://www.devenezia.com/downloads/sas/sascbtbl/). Works without registering the dll.

If I try it the same way with my dll (coying it in system32 folder) I receive the error "Module AD_Wagen could not be loaded.".

I uploaded the c file for example.The dll shoud only return the value 1909 to keep it simple.

In SAS I tried this:

filename SASCBTBL catalog 'WORK.WINAPI.WINAPI.SOURCE';

data _null_;

  file SASCBTBL;

  input ;
  put _infile_;
cards4;
routine AD_Wagen
  module = AD_Wagen
  minarg = 0
  maxarg = 0
  CALLSEQ=BYVALUE
  STACKORDER=R2L
  STACKPOP=CALLER
  returns  = short;
  ARG 1 output num format=ib4.;

;;;;

data _null_;
  rc = modulen ('*i','AD_Wagen');
run;

My Log shows:

NOTE: Module AD_Wagen could not be loaded.

NOTE: Invalid argument to function MODULE at line 522 column 8.

_ERROR_=1 _N_=1

NOTE: DATA statement used (Total process time):

real time 0.00 seconds

cpu time 0.00 seconds

I hope someone could help me.

FriedEgg
SAS Employee

Have you verified that the dll file is working properly iteself, using for instance rundll32 as I suggested earlier?

You define min and maxarg=0 yet you define arg 1, output here does not have any relevance to the value the dll returns.  Output is a argument that is not converted, but is updated with an outgoing value from the DLL routine.

You define module=AD_Wagen, make sure the dll file you placed in you system32 folder is called AD_Wagen.dll or you should change this value.

I also beleive you want stackpop=called instead of caller, but I am not quite sure about this.

It also does look like the function AD_Wagen you are wanting to call has several arguments it is expecting yet as I mention earlier you are defining none.

Best of luck, sorry I cannot provide much help in this area.

chrwag
Calcite | Level 5

I found a solution and it works now.

Testing the dll by calling rundll32 showed that cc3250mt.dll was not found. This dll belongs to the Borland C++ compiler. So I had to install the compiler. I also had to copy the borland dll to my system32 folder.

sas-innovate-white.png

Special offer for SAS Communities members

Save $250 on SAS Innovate and get a free advance copy of the new SAS For Dummies book! Use the code "SASforDummies" to register. Don't miss out, May 6-9, in Orlando, Florida.

 

View the full agenda.

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 7 replies
  • 3503 views
  • 0 likes
  • 3 in conversation