From: xlr82sas on 13 Dec 2009 23:35 On Dec 13, 12:45 pm, Savian <savian....(a)gmail.com> wrote: > On Dec 13, 11:21 am, Francogrex <fra...(a)grex.org> wrote: > > > On Dec 13, 10:17 am, Francogrex <fra...(a)grex.org> wrote: > > > > On Dec 13, 12:36 am, Savian <savian....(a)gmail.com> wrote: > > > > > Do you have control of the dll or is it 3rd party? > > > > I make it myself from the C file I showed above. > > > ok since I got no solutions then I guess it's either not possible or > > I'll need to ask the sas developers at the sas institute because the > > programmers don't seem to know about it. > > Why not use an X command and pass the array in an XML file? You could > also just pass it as a command line argument but I would use XML > instead. Also consider using C# since you are on Windows. C is very > old school. Yes, it works, but consider alternatives. C# EASILY > handles XML so you could be running it in no time. > > Richard D. could answer it but he probably doesn't post on the > weekends. > > Alan Hi, I wish I had a little more time, you asked a very interesting question, I tend to use strings for communicating with other languages. see http://support.sas.com/techsup/technote/ts353.html and http://www.devenezia.com/ Some possible Ideas ( may not work) 1. I think you could create a exe from a dll and use a pipe with stdin stdout(see below) 2. Use modelc and pass a very long string using delimited(or non delimited) hex16. values ie '4F00000000000,56f0000000000' just decode the values in your C program. 3. Consider using Java to call the dll using 9.2 Java obj? 4. Convert you C program to Java an do something like. Here the Java concat command is used concatenate two strings. I think you may be able to call the DLL from java. There is alot more to this on my site. data _null_; length s_out $200; declare JavaObj j1 ('java/lang/String','ABCDE'); declare JavaObj j2 ('java/lang/String','FGHIJ'); j1.callStringMethod ('concat', j2, s_out); put s_out=; j1.delete(); j2.delete(); run; WINDOWS (untested code) where fid contains the highlighted code in the clipboard (highlight code and put "store;gsub '%alansexe' on a function key) filename fmt pipe "c:\cpound\fmt.exe < &fid 2>c:\fmt.log" filename fmt pipe "c:\cpound\fmt.exe < &fid 2>&1"
From: Tom Abernathy on 15 Dec 2009 17:06 Not that I have ever used it, but someone just mentioned using peek or poke on another thread. Couldn't you use that to pass the base address of the array to your function? On Dec 13, 1:21 pm, Francogrex <fra...(a)grex.org> wrote: > On Dec 13, 10:17 am, Francogrex <fra...(a)grex.org> wrote: > > > On Dec 13, 12:36 am, Savian <savian....(a)gmail.com> wrote: > > > > Do you have control of the dll or is it 3rd party? > > > I make it myself from the C file I showed above. > > ok since I got no solutions then I guess it's either not possible or > I'll need to ask the sas developers at the sas institute because the > programmers don't seem to know about it.
From: Jonathan Goldberg on 15 Dec 2009 18:41 Assuming you are running on a 32 bit platform, you should try the addr() function. I haven't tried this, but I suggest you do two things: 1) put your data into a _temporary_ array to insure that the values are stored in contiguous memory locations 2) pass y = addr(yourarry(1)); On a 64 bit platform use addrlong(); Note: addr() returns the address of a numeric variable. Addrlong() returns the address of a character variable. Whichever, you will need to have your data be the appropriate type on the SAS side and do any needed conversions in your dll. Also, addrlong() works in both environments and is the recommended method for this reason. HTH. Jonathan On Sat, 12 Dec 2009 06:44:07 -0800, Francogrex <franco(a)GREX.ORG> wrote: >Hi, This isn't an easy question, actually it's very tough and I expect >only very experienced programmers to know the answer. I'm trying to >use the modulen function to let sas connect and use a dll. My dll >takes as an input a pointer and an integer and returns a pointer. Here >is the code of the dll that I called sas.dll: >#ifdef BUILD_DLL >#define EXPORT __declspec(dllexport) >#else >#define EXPORT __declspec(dllimport) >#endif >#include <stdio.h> >#include <stdlib.h> >EXPORT double __stdcall *test (double *x, int n) >{ > double *end=malloc((n+5)*sizeof(double)); > int i; > for (i=0; i<n;i++) > { > *end=x[i]*2; > } > return(end); >} > >Now from SAS I use: > >filename sascbtbl catalog 'work.api.ZIAD'; >data _null_; > file sascbtbl; > input; > put _infile_; > cards4; > routine test > minarg=2 > maxarg=2 > stackpop=called > module=sas > returns=long; > >arg 1 num input byaddr format=RB8. ; >arg 2 num input byvalue format=PIB4. ; >;;;; >run; >data _null_; > array vals(4) (12 2 13 4); > rc= modulen ('*e', 'test',vals(1),1); > put rc=; > testme=peek(rc,8); > put testme=; >run; > >This works well. Giving: rc=72351536 and testme=24 > >But I am just giving one values as an argument to the sas.dll. What I >want is to directly pass the WHOLE array arr as an argument (pointer) >and then use something like > >rc= modulen ('*e', 'test', {WRONG SYNTAX ALL ARRAY vals}, 4); >ret1=peek(rc,8) ; >ret2=peek(rc+8,8); >etc.. >to read the returned result. Any ideas how?
From: S=?ISO-8859-1?Q?=C3=B8ren?= Lassen on 16 Dec 2009 02:56 Franco, I do not think your approach is quite the right one. Even if you succeed, you would probably have a memory leak, as you allocate the return values with malloc, but the memory is (as far as I can see) not released again anywhere. If you want to take data from an array and return the data in another array, you should probably let SAS allocate both arrays. Something like this: data x; array vals(4) (12 2 13 4); array returns (4) 8; call module('*e','test',vals(1),returns(1),4); run; That way, SAS will take care of allocating and deallocating the memory. Your C routine would then look something like EXPORT void test (double *inarray, double *outarray, int n) { int i; for (i=0; i<n;i++) { outarray[i]=inarray[i]*2; } return; } Of course, the call may be made more elegant and foolproof by putting it in a macro: %macro doublearray(inarray,outarray, n=min(dim(&inarray),dim(&outarray)) ); call module('*e','test', &inarray(lbound(&inarray)), &outarray(lbound(&outarray)), &n) %mend; Regards, Søren On Sat, 12 Dec 2009 06:44:07 -0800, Francogrex <franco(a)GREX.ORG> wrote: >Hi, This isn't an easy question, actually it's very tough and I expect >only very experienced programmers to know the answer. I'm trying to >use the modulen function to let sas connect and use a dll. My dll >takes as an input a pointer and an integer and returns a pointer. Here >is the code of the dll that I called sas.dll: >#ifdef BUILD_DLL >#define EXPORT __declspec(dllexport) >#else >#define EXPORT __declspec(dllimport) >#endif >#include <stdio.h> >#include <stdlib.h> >EXPORT double __stdcall *test (double *x, int n) >{ > double *end=malloc((n+5)*sizeof(double)); > int i; > for (i=0; i<n;i++) > { > *end=x[i]*2; > } > return(end); >} > >Now from SAS I use: > >filename sascbtbl catalog 'work.api.ZIAD'; >data _null_; > file sascbtbl; > input; > put _infile_; > cards4; > routine test > minarg=2 > maxarg=2 > stackpop=called > module=sas > returns=long; > >arg 1 num input byaddr format=RB8. ; >arg 2 num input byvalue format=PIB4. ; >;;;; >run; >data _null_; > array vals(4) (12 2 13 4); > rc= modulen ('*e', 'test',vals(1),1); > put rc=; > testme=peek(rc,8); > put testme=; >run; > >This works well. Giving: rc=72351536 and testme=24 > >But I am just giving one values as an argument to the sas.dll. What I >want is to directly pass the WHOLE array arr as an argument (pointer) >and then use something like > >rc= modulen ('*e', 'test', {WRONG SYNTAX ALL ARRAY vals}, 4); >ret1=peek(rc,8) ; >ret2=peek(rc+8,8); >etc.. >to read the returned result. Any ideas how?
From: Jonathan Goldberg on 16 Dec 2009 10:22 Soren: Good catch. Gad, it's been a long time since I programmed in C. Those were the days... Your modified code calls the module routine. This is necessary if the routine called does not return a value. The original code called modulen and specified the return type as long. Since the C code writes multiple values directly to memory it's a little obscure which is correct; however, Franco might try it your way to see if it helps. On Wed, 16 Dec 2009 02:56:31 -0500, S=?ISO-8859-1?Q?=C3=B8ren?= Lassen <s.lassen(a)POST.TELE.DK> wrote: >Franco, > >I do not think your approach is quite the right one. >Even if you succeed, you would probably have a memory leak, >as you allocate the return values with malloc, but the >memory is (as far as I can see) not released again anywhere. > >If you want to take data from an array and return the >data in another array, you should probably let SAS allocate >both arrays. Something like this: > >data x; > array vals(4) (12 2 13 4); > array returns (4) 8; > call module('*e','test',vals(1),returns(1),4); >run; > >That way, SAS will take care of allocating and deallocating the >memory. > >Your C routine would then look something like > >EXPORT void test (double *inarray, > double *outarray, > int n) >{ > int i; > for (i=0; i<n;i++) > { > outarray[i]=inarray[i]*2; > } > return; >} > >Of course, the call may be made more elegant and foolproof by >putting it in a macro: > >%macro doublearray(inarray,outarray, > n=min(dim(&inarray),dim(&outarray)) ); > call module('*e','test', > &inarray(lbound(&inarray)), > &outarray(lbound(&outarray)), > &n) >%mend; > >Regards, >Søren > > >On Sat, 12 Dec 2009 06:44:07 -0800, Francogrex <franco(a)GREX.ORG> wrote: > >>Hi, This isn't an easy question, actually it's very tough and I expect >>only very experienced programmers to know the answer. I'm trying to >>use the modulen function to let sas connect and use a dll. My dll >>takes as an input a pointer and an integer and returns a pointer. Here >>is the code of the dll that I called sas.dll: >>#ifdef BUILD_DLL >>#define EXPORT __declspec(dllexport) >>#else >>#define EXPORT __declspec(dllimport) >>#endif >>#include <stdio.h> >>#include <stdlib.h> >>EXPORT double __stdcall *test (double *x, int n) >>{ >> double *end=malloc((n+5)*sizeof(double)); >> int i; >> for (i=0; i<n;i++) >> { >> *end=x[i]*2; >> } >> return(end); >>} >> >>Now from SAS I use: >> >>filename sascbtbl catalog 'work.api.ZIAD'; >>data _null_; >> file sascbtbl; >> input; >> put _infile_; >> cards4; >> routine test >> minarg=2 >> maxarg=2 >> stackpop=called >> module=sas >> returns=long; >> >>arg 1 num input byaddr format=RB8. ; >>arg 2 num input byvalue format=PIB4. ; >>;;;; >>run; >>data _null_; >> array vals(4) (12 2 13 4); >> rc= modulen ('*e', 'test',vals(1),1); >> put rc=; >> testme=peek(rc,8); >> put testme=; >>run; >> >>This works well. Giving: rc=72351536 and testme=24 >> >>But I am just giving one values as an argument to the sas.dll. What I >>want is to directly pass the WHOLE array arr as an argument (pointer) >>and then use something like >> >>rc= modulen ('*e', 'test', {WRONG SYNTAX ALL ARRAY vals}, 4); >>ret1=peek(rc,8) ; >>ret2=peek(rc+8,8); >>etc.. >>to read the returned result. Any ideas how?
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: Programmer Productivity using EE, Next: need help with the GLIMMIX for Goodness-of -fit |