A quick follow up to building DLL’s

Another slight issue I’ve found with the SLiRP code, is that it expects to be able to call two functions (slirp_can_output and slirp_output). The snag here is that DLL’s expect to be SELF CONTAINED… So how can you have a DLL that needs to call functions from your program?

Void pointers!

So let’s make this more… involved.

dll.c

void (*bob)(int xy);

__declspec(dllexport) int hi(void)
{
(*bob)(12);
return 3;
}

__declspec(dllexport) void Register(void *p)
{
bob=p;
}

test.c

extern void Register(void *p);

void XX(int xy)
{
printf(“XX %d\n”,xy);
}

void main(void)
{
int j;
Register(XX);
j=hi();

printf(“%d\n”,j);
}

And let’s build it…

c:\temp\dll>cl /c /LD dll.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80×86
Copyright (C) Microsoft Corporation. All rights reserved.

dll.c

c:\temp\dll>link /DLL dll.obj
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.

Creating library dll.lib and object dll.exp

c:\temp\dll>cl test.c dll.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80×86
Copyright (C) Microsoft Corporation. All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.

/out:test.exe
test.obj
dll.lib

c:\temp\dll>test
XX 12
3

So as we can see, the main procedure runs the ‘register’ procedure to tell the dll that the ‘bob’ procedure will infact be XX. Now when the dll invokes it’s ‘hi’ function it can call the XX function from the exe. Now if I were a better programer, I’d use the DLLMain code to make sure that all my virtual void functions cause some kind of ‘readable’ panic message when called so you don’t get the default reaper… Because naturally if you run the dll code without the register function it’ll crash in a not so great manner.

But I’ll leave that as an exercise to the reader.

I’ve made some good progress on the SIMH thing, Ive got the non networked versions & the libpcap stuff building with Visual C++ 2008… I was thinking about using that 2010 RC but that just seems wrong…. But for now all I’ll have to do is apply this logic to the slirp dll, and get building the VC version for linking, and the Mingw version for actual operation….

Build a DLL

Well this is leading up to a new release of my SIMH projects. The issue that I’ve had with the SLiRP code (usermode NAT) is that it only works when built with GCC, and ONLY when you have no optimizations. Naturally you will loose all optimizations with SIMH if you build the entire project like that. And of course you cannot use Visual C++ to build SIMH, because while it’s faster they use different object files.

So while thinking about what a bummer it is, and how to try to debug SLiRP with Visual Studio, today I had a ‘better’ idea. Well ‘better’ in that I can do this way quicker.

Instead I’ll build SLiRP as a DLL, and have Visual C++ call that!

Ok, now that sounds crazy, but the first thing I’d need is a simple ‘test’ case. First let’s build a dll in MinGW. It took a bit of googling but then I found this super simple example.

dll.c

__declspec(dllexport) int hi(void)
{
return 3;
}

Ok, it doesn’t do that much, but you get the idea. Now we have to compile this with MinGW.

gcc -c dll.c
gcc -shared -o test.dll dll.o

Ok, now this will first compile the C file into an object file, then the linker will set it up as a DLL. Notice that I’m not building the ‘.a’ export file for this DLL. Visual C++ wouldn’t like it anyways, so I don’t need it.

Next, using Visual C++ (I would *assume* just about every version can do this..) I re-build the DLL to create the export library. Yes I know this is weird, but it is the quickest way I know to do this.

cl /c /LD dll.c
link /DLL dll.obj

Cool, now we’ve built dll.c as a DLL under both MinGW & Visual C++. Now for a ‘test’ program to drive our ‘staticly linked’ dynamic link library.

test.c

void main(void)
{
int j=hi();
printf(“%d\n”,j);
}

Ok, now with that out of the way, let’s compile & link!

cl test.c dll.lib

Cool, now we’ll have a test.exe!

Let’s run it!

c:\msys\1.0\src\dlltest>cl test.c dll.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80×86
Copyright (C) Microsoft Corporation. All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.

/out:test.exe
test.obj
dll.lib

c:\msys\1.0\src\dlltest>test
3

Wow that was exciting! Now for the people paying attention, you’ll remember that the test.exe was linked against dll.lib which was built with the Microsoft compiler, and is calling the Microsoft generated dll.dll. Yes you are correct. But always test with a known positive, before you throw in the negative I say…

c:\msys\1.0\src\dlltest>move test.dll dll.dll
Overwrite c:\msys\1.0\src\dlltest\dll.dll? (Yes/No/All): y
1 file(s) moved.

c:\msys\1.0\src\dlltest>test
3

Holy crap! It worked!!!!

That’s right, now I have built a very simple test program that’ll call a DLL function built with MinGW!

And that, is how you can get around a kooky problem where some programs build with one version of a compiler tweaked one way, and you want to use those bits in another program built another way.

Just ask any language refugee from the 1980’s how hard this was to do on the PC platform.. While VMS had a common library spec for all languages, not every platform (MS-DOS,UNIX) was as lucky. But with the rise of things like Windows with DLL’s, and of course NT thanks to the VMS crew it’s in modern systems today.

Let me tell you, linking Quick Basic to C was… not all that much fun. And Turbo C++ was right out!

Anyways I’ll leave you with this much, and at the worst case, much like making bootable CD’s, it’s a good note for me to find this stuff later when I need it.

SIMH on the DEC Alpha…

I released a partial binary build of SIMH on the DEC Alpha using Visual C++ 6.0 … I didn’t think much of it, but it’s been downloaded 400% more then I had thought…. (I didn’t think anyone would!)…

I can either conclude that:

  • There are some DEC Alpha NT users still out there…
  • Some people download things for the sake of downloading…

If you are one of the four remaining users, let me know… I have Visual C++ 6 I can try to build other stuff….

In the meantime, here is VMS on WNT…

VAX./VMS running on a Dec Alpha / NT machine

 

Some updates..

I had a request for the qemu 0.90 binaries to run NeXTSTEP… I don’t own Vaxenrule.com anymore so for now I’ll put them here:

http://dl.dropbox.com/u/1694005/qemu090%20for%20nextstep.zip

Sorry for the bitrot stuff… 😐 At least I’m still here.

Also while working on Tradewars C today, I came across this great package called OpenDoors. Even better is that it’s under the LGPL. The only “downside” is that OpenDoors requires Visual C++ 6.0 or higher to build, because of the toolbar.. Also I’m not sure if going from VC 1.0 to 9.0 didn’t flake some stuff out as well… I’m not 100% sure about it, but the trading part of the game feels.. weird.

The examples are pretty straight forward, and it took a few hours on & off for me to convert the standalone tradewars into a door program. I like the feel of it so much I may try to see about converting SIMH to run with it.. Maybe even dumbfrotz.

OpenDoors trade wars

OpenDoors trade wars

Above is a picture of what the console looks like.

Visual C++ 4.0 arrived today!

For the RISC cpu!… That being Alpha & MIPS. Although the back of the box does mention PowerPC there is no PowerPC anything here…

Visual C++ 4.0 RISC box

Visual C++ 4.0 RISC box

I always did like the old Microsoft boxes during this time period… They always looked somewhat professional, not like today’s weird boxes that look like some kind of toy should be inside.

Also speaking of RISC cpu’s check the back of the Visual C++ 2.0 for mips box:

Visual C++ 2.0 MIPS box back

Visual C++ 2.0 MIPS box back

You have to remember it was “time” the golden age of the promised RISC cpu… Intel was hitting that wall with the 486, but lo the pentium changed all of that. And the Pentium PRO cemented all the little RISC cpu’s death. It’s funny how at the same time the “itanic/itanium” is just as dead as well.. MIPS. At least MIPS has their embedded space.. Which is funny looking back at the R4000 as a workstation CPU, and now it’s available in handhelds & set tops.. Although the Acorn derived strongarm is well… Strong-arming MIPS & Power for embedded dominance.

I’m pretty sure that Visual C++ 4.0 brought a lot of Windows 95 like functionality to NT, so I’ll have to see just how much(or little) of modern stuff will build. According to this link, 4.0a was the LAST version to support the MIPS, so Unless I can find 4.0a this is as good as it’s going to get.

If anyone has either insight on where to get Visual C++ 4.0a for the MIPS, or even where to get NT 3.1 for the Alpha give me a line…. Not to mention service pack 3 for the MIPS running NT 3.1… I have a feeling the shiped kernel is at fault in the emulator…

Microsoft eMbedded Visual C++ 4.0

Well I was looking for a way to cross compile to the MIPS and also if I could use my old Platform builder 2.11… Anyways Platform builder has cross compilers, but no libraries, I figured you need the eMbeded Visual C++.. And as luck has it, you can download it right here!. Also you’ll probably want service pack 4.(local mirror), and don’t forget the code TRT7H-KD36T-FRH8D-6QH8P-VFJHQ

System Requirements

  • Supported Operating Systems: Windows 2000; Windows XP
  • Microsoft Windows® 2000 Professional SP2, Microsoft Windows 2000 Server SP2, or Microsoft Windows XP Professional
  • A desktop computer with a Pentium-II class processor, 450 MHz or faster
  • 96 MB (128 MB recommended) memory for Windows 2000 Professional or Windows XP Professional. 192 MB (256 MB recommended) memory for Windows 2000 Server.
  • 200 MB hard disk space
  • CD-ROM drive
  • VGA or higher-resolution monitor. A Super VGA (800 x 600 or larger) monitor is recommended.
  • Mouse or compatible pointing device

If your machine is NOT up to this kind of capability, then you can download the older eMbedded Visaul C++ 3.0, that will run on Windows NT 4.0 (i386 of course). Purdue also had a nice walkthrough on installing the 3.0 tool kit.

I DO recommend that you install IIS on your cross compiling machine, as it’s an easy way to move your object files to the MIPS host for linking.

It is worth noting that Visual C++ 4.0’s emulator will NOT run under Virtual PC.. They use the same call set, and it thinks VPC is Windows CE… I know it’s confusing.

I would imagine everyone could run this. Well if they were so inclined.. Well the installation is pretty simple but now for the ‘fun’ stuff.

First let’s download the source code to Quake.. ID software has been most kind to provide the Quake engine under the GPL!. So we can use it for a MIPS cross compile test.. (As far as I know there is no Dec Alpha cross compiler, but there is a PowerPC.. Anyone use a PowerPC NT machine?). You can download it here. .This went nowhere, as it turns out WindowsCE and Windows NT use different models for floating point, and are incompatible.

Ok with your embedded tools installed, we are now going to merge our Visual C++ MIPS CD so we use it for libraries & include files.. Since we are all going to use the same compiler it’ll be somewhat easy.. I’m using the tools out of “C:\Program Files\Microsoft eMbedded C++ 4.0\EVC\WCE400”

11/27/2001. 03:00 AM........ 1,073,152 C1XX_MP.DLL
11/27/2001. 03:00 AM.......... 581,632 C1_MP.DLL
11/27/2001. 03:00 AM........ 1,056,768 C2_MP.DLL
11/27/2001. 03:00 AM........... 69,632 CLMIPS.EXE
06/13/2001. 03:00 AM.......... 180,276 MSPDB60.DLL

To make it “feel” like visual c++ 2.0 I’m going to put them in the c:\msvc20\bin directory on my HOST pc (Vista Pro x64).. Then I simply copy the include & lib directory from the MIPS Visual C++ CD into the corresponding directories on my host.. We are ALMOST there.

The next thing I did was to grab an intel copy of Visual C++ 2.0 (I almost be dammed near all of them can do this..) and take it’s linker.. The linker out of the embedded tools is obsessed with the WindowsCE subsystem which won’t help us at ALL.

09/16/1994. 01:00 PM........... 67,584 DBI.DLL
09/16/1994. 01:00 PM........... 12,980 LINK.ERR
09/16/1994. 01:00 PM.......... 420,352 LINK.EXE

Go ahead and place those files into the c:\msvc20\bin directory.

Now we just need to create a simple batch file to keep our environment in order:

set LIB=c:\msvc20\lib
set PATH=c:\msvc20\bin;%path%
set include=c:\msvc20\include

Save that to something like mipvars.cmd, and run it & we should be ready to start compiling!

To test the cross compiler I’m going to build a SIMPLE program that has 2 files.

hi.c


#include <stdio.h>

extern int bob(void);

void main(void)
{
printf("%d",bob());
}

bob.c

int bob(void)
{
return 3;
}

Ok, now we compile it like so:

C:\msvc20>clmips *.c -o bob.exe
Microsoft (R) C/C++ Optimizing Compiler Version 12.20.9419 for MIPS R-Series
Copyright (C) Microsoft Corp 1984-2001. All rights reserved.

bob.c
hi.c
Generating Code...
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.

/out:bob.exe
/out:bob.exe
bob.obj
hi.obj
LINK : error LNK1104: cannot open file "corelibc.lib"

Oh no trouble!. Because this was all ripped from the embeded tools it wants to think it has corelibc not libc.. But we can cheat, just copy libc.lib to corelibc.lib and I’ve also copied rpcndr.lib to coredll.lib to satisfy the linker.. Now when we re-compile:

C:\msvc20>clmips *.c -o bob.exe
Microsoft (R) C/C++ Optimizing Compiler Version 12.20.9419 for MIPS R-Series
Copyright (C) Microsoft Corp 1984-2001. All rights reserved.

bob.c
hi.c
Generating Code...
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.

/out:bob.exe
/out:bob.exe
bob.obj
hi.obj

That’s right, we got an executable!. Now if you run it on your x86(or x64) host you’ll get this:

c:\msvc20\bob.exe is not a valid Win32 application.

And of course, since you installed IIS on your HOST (or cross compiling VM) you can connect to it from your MIPS VM, download the exe & run it.

MIPS cross compile
MIPS cross compile

I’m kind of surprised it worked.. It does go to show though, that somewhere inside Microsoft they have some COOL cross compiler technology, it’s just too bad they didn’t make it into an easy package for the RISC stuff.. But now that the MIPS is coming back to life via Qemu, and NT 4.0 can be had for $5 a retail box on ebay, I figure it’s worth this much for those people who can find Visual C++ for MIPS/RISC.

Visual C++ 2005 project & exe’s for SIMH 3.7-3

I’ve uploaded onto the sourceforge site, my project source & the resulting exe’s

I need to see which compiler generates the faster exe, and ship with that going forward for the win32 platform. I suspect its VC2005, but the race is going to be between VC2005, gcc/mingw, Watcom 11.

Of course if anyone want’s to suggest another C compiler for win32, I could always try it out, and see how it performs.

Of course today is 9/11… It’s hard to believe that it’s been 6 years. One can only hope the madness will end.