Archive for the ‘Programming’ Category
UPDATE: I have investigated further and it seems that it is somehow related to differences between stdin when read from a redirected file and a pipe stream. I tested with Sun Studio and received a similar error, so it seems that this is not compiler specific. Btw. the code I am testing/wrapping fails when trying to “BACKSPACE” (previous record) in the read input. Found some info that might relate somehow to the difficulties I am facing at the Intel Forum.
My current hobby project is trying to wrap a NASA legacy program for chemical equilibrium calculations (NASA CEA) in python. The first step has been tweaking the program to read input from stdin (unit 5 in fortran) and write output to stdout (unit 6 in fortran). In its current state it reads from an input file and writes to another file. This was faily easy to accomplish by changing the unit numbers. So far so good. It works fine if a run the program with stdin and stdout redirected like
cea2 < input > output
However, things go wrong if i use piped stdin like
cat input | cea2 > output
I really need this, since I would like to use the subprocess.Popen in python in order to communicate with the program through piped input.
I am not a fortran programmer, and it is likely that I have done something wrong. This has been my working hypothesis so far. The program fails with a message saying somthing like “Illegal seek” and the IOSTAT exit code is 29 (STATUS= specifier on an OPEN statement is invalid. According to this site), and it happens when the program tries to “backspace” in the read input. Somehow it may be stock at the end of file or something like that. A lot of googling didn’t bring up much, except this bug report for gfortran. According to the mail archive it should be fixed in versions 4.4, 4.5, and 4.6. I am running Linux Mint 11 with gcc 4.5.2. However, the upstream bug fix may not have surfaced in the downstream gcc package installed on Mint 11. I will try a live distro with gcc 4.6 one of these days, likely Mint 12, to see if it helps.
I have set up a google code site in order to maintain the work done, I have called the python wrap for cea2py.
I was trying to use pydb with ddd in order to debug a python script. However when invoking ddd with e.g.
ddd clamied that it could not find pydb. I tried running pydb from the command line and I was left with a message like
The program 'pydb' is currently not installed. You can install it by typing:
sudo apt-get install pydb
pydb: command not found
Ok, so I tried to install it
sudo apt-get install pydb
Reading package lists... Done
Building dependency tree
Reading state information... Done
pydb is already the newest version.
Hmmm, strange. Google, google, google……….
It turned out that some else had experienced the same problem as me and provided a fix. Apparently the link to pydb in /usr/bin is broken. The fix is
sudo rm /usr/bin/pydb
sudo ln -s /usr/lib/python2.4/site-packages/pydb/pydb.py /usr/bin/pydb
In this post it is described in a step-by-step manner how to create a C/C++ dynamic linked library (DLL) for use with Visual Basic for Applications (VBA) in Microsoft Excel. Main emphasis is on using the DLL for scientific computations, thus it is necessary to be able to send arrays as input to the DLL and receive arrays as output. Only a very simple example will be given in order to illustrate this. It has been prioritized to show a working example rather than elaborating too much on C/C++ calling conventions, name decoration of exported function etc. For more information on these topics please consult the web (see e.g. the Further reading section below).
In order to follow the given example it is required to have a working installation of Microsoft Windows (example only tested on XP, but is assumed to work as well on Windows 2000 and Vista), including Microsoft Office (tested on Office 2000, but works as well with Office 2003 and 2007 I presume), and finally an installation of Microsoft Visual C++ 2008 (Express Edition). Visual C++ can be downloaded free of charge from Microsoft. If problems with the installation are experienced, seek assistance in the installation and setup forum.
Creating the DLL with Visual C++
Paste the code below into a text editor and save it as dllarray.cpp.
extern “C” int __declspec(dllexport) _stdcall myarray( double* pin, double* pout, int sz )
for (i = 0; i < sz ; i++)
The function “dllarray” takes two arrays as input (actually pointers to the adress of the first element of each array) along with the number of elements in the arrays (in this case the same). The function loops through the arrays and writes element i in pin times 100 to element i in pout (not really that scientific ;-). The return type of the function is an iteger (in this case 0), but error checking could be included as well with different return values. In order to compile the code open the Visual Studio 2008 Command Prompt
and change directory to the location of the file just created. Compile the source file with:
cl /c /LD dllarray.cpp and link with:
link /DLL dllarray.obj
This creates the DLL (dllarray.dll). In order to refer to the functions defined inside the dll it is necessary to extract the function names really exported (some name decoration has occured). This is achieved with the DUMPBIN tool shipped with Visual C++. On the VS2008 command line type:
dumpbin /EXPORTS dllarray.dll
This gives the following output:
Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file myarray.dll
File Type: DLL
Section contains the following exports for myarray.dll
481F8D73 time date stamp Tue May 06 00:42:59 2008
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 00001000 _myarray@12
From which it is inferred that the exported name of the function myarray is actually _myarray@12.
Calling the DLL from inside VBA in MS Excel
Open an empty workbook in Excel and enter the VBA editor (Alt+F11). Make a new module and paste the following code into it:
Declare Function myarray& Lib “C:\dllarray.dll” Alias “_myarray@12” _
(ByRef pin As Double, ByRef pout As Double, ByVal sz As Long)
Dim sz As Long
Dim pin() As Double
Dim pout() As Double
sz = 10
ReDim pin(sz – 1), pout(sz – 1)
For i = 0 To (sz – 1)
pin(i) = i
y = myarray(pin(0), pout(0), sz)
MsgBox (“Value of 4. element in pin array : ” + Str(pin(3)))
MsgBox (“Value of 4. element in pout array : ” + Str(pout(3)))
Run the code. This should pop up two message boxes, the first showing the value of the 4. element of the “input” array and the second showing the corresponding value written to the “output” array. The following conventions are very important when passing arrays to a C/C++ DLL
- In the function declaration of the DLL the arrays should be passed “ByRef” (default) which passes the address of the first element rather than the value.
- Integers (int) in C/C++ should passed as long’s from VBA.
- The name following Declare Function is the name which is used in VBA (does not have to be the same as in the DLL), however the real (exported) name of the function in the DLL should be specified after the Alias (in this case with name decoration).
- When calling the declared function the first element should be given, not the entire array.
- When writing output to arrays in VBA from a C/C++ DLL it is by far the easiest approach to hand in the (empty) “output” arrays as input to the function. Using the pointer approach here the DLL can modify the arrays defined in VBA.
The above example with C++ can easily be modified to apply for ANSI C as well. Change the extension of the source file from *.cpp to *.c. Delete the extern “C” declaration and add the following option to the command line compiler /TC.