Merging modern software development with electrons and metal
Random header image... Refresh for more!

Category — Development Techniques

VB6 Notes – Determining the calling convention of a C DLL

OK, this isn’t just for VB6, but I needed to call a function in a C DLL from VB6, and VB6 can only call functions that use the stdcall calling convention.

A properly written C DLL is easy to use from VB6, but a C DLL not written with VB6 in mind may require an adapter layer. C++ DLLs are typically very difficult to use from another compiler (or VB), due to incompatibilities in areas such as name mangling. Of course, COM DLLs and .NET assembly DLLs are totally different cases. COM objects are almost always easy to call from VB6. .NET assemblies are like C DLL’s: when properly designed with a COM interop, using them is like using a COM object, but if they’re not designed with COM in mind, then they can’t be used.

If you have the source or header files, you should be able to determine the calling convention – although you may have to know a bit about the compiler, too (so you know what the default convention is, and how each convention is identified).

A second method that sometimes works is to use Microsoft’s dumpbin program. You can get dumpbin for free by downloading and registering Visual C++ 2005 Express Edition (notes on Win32 development here) . By dumping the Export list and looking at the decorated names, you can determine the calling convention. I got the idea for this approach from here.

For a function defined as void foo(int a), its decorated name would be:

  • _foo for __cdecl (C calling convention)
  • _foo@4 for __stdcall (Windows calling convention)
  • @foo@4 for __fastcall

I used dumpbin /EXPORTS path_to_dll from the Visual C++ 2005EE command prompt. However, not all DLLs export the decorated names, even for DLLs created with MS VC++. I’ve seen some that do and some that don’t; it might have to do with how the exported names are declared (e.g. in a DEF file). Non-Microsoft C compilers (MingW, gcc, Borland, etc) might decorate names differently.

By the way, you can use dumpbin /DEPENDENTS path_to_DLL to see what DLLs a DLL requires.

Another way is to use Python and the ctypes module. The ctypes module is included in Python 2.5; it’s an add-on to earlier versions. ctypes can load a DLL as either a Windows (stdcall) DLL using windll.LoadLibrary or a C (cdecl) DLL using cdll.LoadLibrary.

Here’s an example using Python and two functions in the MEI PC/DSP 2.5.09 MEDVC60F.DLL. One function (dsp_init) is stdcall; the other function (find_pci_dsp) is cdecl.

>>> from ctypes import *
>>> stdcall = windll.LoadLibrary(‘C:\\medvc60f.dll’)
>>> cdecl = cdll.LoadLibrary(‘C:\\medvc60f.dll’)
>>> ShortArray20Type = c_short * 20
>>> addr = ShortArray20Type()
>>> irq = ShortArray20Type()
>>> numBoards = c_short(0)
>>> cdecl.find_pci_dsp(byref(numBoards), byref(addr), byref(irq))
0
>>> stdcall.find_pci_dsp(byref(numBoards), byref(addr), byref(irq))
Traceback (most recent call last):
File “<interactive input>”, line 1, in <module>
ValueError: Procedure probably called with too many arguments (12 bytes in excess)
>>> cdecl.dsp_init(0×300)
Traceback (most recent call last):
File “<interactive input>”, line 1, in <module>
ValueError: Procedure called with not enough arguments (4 bytes missing) or wrong calling convention
>>> stdcall.dsp_init(0×300)
2

October 25, 2007   No Comments

Write Microsoft .NET code faster with Boo

even if you’re using C# or VB.NET. How? By using Boo’s interpreter to try out ideas, test usage of .NET framework functions, and interact with components (COM, .NET). Then when you’re comfortable, you can write the polished code in the language of your choice.

This is one use for mixed language programming, mentioned by me here, but where the final software might not use both languages.

In fact, any .NET interpreter such as IronPython or IronRuby could be used. And it’s a great technique for other than .NET – I’ve used it a lot with Python on Win32, and you can use it in Java with JRuby, Jython, Groovy, etc. This approach could be very useful for embedded and factory software development.

On .NET IronPython and IronRuby have advantages because they’re official Microsoft languages (and IP has a book coming out – IronPython In Action) and the languages are already in wide use (Win32, *nix, Java). I’m using Boo because it comes with the open source SharpDevelop IDE, and right now it integrates better with .NET (IP does not support attributes well, and it’s not easy to make an IP assembly callable by other .NET languages, etc).

Short example – interactively using DirectoryInfo in Boo (text I typed in bold):

>>> di = DirectoryInfo(“C:\\Download”)
C:\Download
>>> files = di.GetFiles()
(AdbeRdr80_en_US.exe, AdbeRdr80_en_US_Nosso_error.log, Firefox Setup 2.0.0.1.exe, SharpDevelop_2.2.1.2648_Setup.msi, TortoiseSVN-1.4.3.8645-win32-svn-1.4.3.msi)
>>> files = di.GetFiles(‘t*’)
(TortoiseSVN-1.4.3.8645-win32-svn-1.4.3.msi)

Interactively calling a COM object in Boo:

>>> ieType = System.Type.GetTypeFromProgID(‘InternetExplorer.Application’)
System.__ComObject
>>> ie = System.Activator.CreateInstance(ieType)
System.__ComObject
>>> ie.Visible
false
>>> ie.Visible = true
true
>>> ie.Visible
true

So far I haven’t had to use InvokeMember to call COM functions. At least for C# and VB.NET (and probably Boo) it appears you need to use it if you are using late binding. BTW, it is possible to use late binding with COM events, but it is significant extra work.

Tony

September 26, 2007   No Comments

The purpose of Test Driven Development

I was going through an old stack of JDJ’s (Java Developer Journals), and saw an interesting commentary on Test Drive Development (TDD). The author said its purpose was to help you write the minimal amount of code necessary to meet the current requirements, and that having a test suite available was a nice side affect. His TDD development sequence is:

  1. Write tests that show your requirements, based on the perfect client interface
  2. Write just enough code to compile successfully
  3. Write just enough so that all the tests pass
  4. Refactor

Now apply this idea to the world of factory automation software. Hmm, could be interesting, but it wouldn’t work with PLC’s (rllUnit anyone? I don’t want to even imagine porting xUnit to IEC61131.)

Tony

July 21, 2007   No Comments

Software Development Trends

Here is my quick overview of modern software development trends. It’s somewhat quirky, but software development is a big area, all the way from programming $0.50 PIC micros in toaster ovens to massive web services and supercomputers.

Where do I pick up these trends? From trade magazines (after applying my hype discount factor), web blogs, discussions with other programmers, and what works for me.

  • Version Control and Bug Tracking that work. These are essential for good development, but I suspect that most automation developers, at least at small companies, still do not use them.
  • Design Patterns – a good way of talking about software architecture.
  • Unit testing and Test Driven Development – somewhat hard to apply to automation software, but definitely making waves right now in desktop and web development.
  • Refactoring – restructuring and improving existing software, instead of doing a ground-up re-write.
  • Agile Development – iterative, customer focused development instead of BDUF (Big Design Up Front).
  • Dynamic languages – allow rapid development, better re-use of existing components, run time customizations.
  • Mixed language development – use appropriate tool for the job. A desktop example is Adobe Lightroom, written in Lua and C. I do a lot of this (especially when including IEC 61131 as a language)
  • Web technologies – interesting stuff, but I think factory software developers should not get caught up in the hype.
  • Open Source – some very good products to add to your toolkit.

I plan on discussing many of these techniques in the future, using concrete examples of the tools I use and like. For example, I will use Subversion when discussing version control.

Tony

June 21, 2007   No Comments

Trends to use – Open Source Software

Open source software is a great resource. If you’re going to use and modify open source code in your machine, then you have to look at licensing issues very carefully. But there is another way to take advantage of open source software – by using open source projects such as Subversion to enhance your development process with no licensing worries.

Even if the majority of open source software can safely be ignored, there are many rock solid, high quality, well documented, Windows-friendly projects. Examples include:

  • Subversion for version control with TortoiseSVN client for Windows
  • Trac for project management and bug tracking
  • Apache web server
  • xUnit for unit testing
  • Wix for MSI installers (OK, its documentation is a little weak, but it’s still what I use to create Windows installers)
  • Programming languages such as Python, IronPython on .NET, and Lua.

What are some of the advantages of these top notch projects?

  • High quality. For example, Subversion has a better reputation than Microsoft’s SourceSafe.
  • Low cost, both in money (nothing) and time (due to good documentation).
  • Ease of deployment – with Subversion, I don’t have to worry about how many users there are. Adding another user costs exactly $0.00, unlike adding a user on a commercial version control system
  • No licensing hassles; there are no hardware keys, no software keys, and no chance of any software license audits.
  • More stable path – no forced upgrades (upgrade when you’re ready), no worries about the vendor going out of business, no vendor agendas to worry about.
  • Often commercial help is available if desired – so far I’ve done fine with the documentation and Google.

Tony

June 14, 2007   No Comments