views:

703

answers:

3

I have a lot of legacy code which I currently compile using an antiquated install of Borland C++ 3.0.

There's a rules engine in this code that I'd like to extract and use in a C# .NET application.

The thing is, if I extract the rules engine into it's own DLL, I want to be able to call this DLL from both the existing legacy code which I don't have time to port, and from the C# .NET app.

If I build a DLL using the old Borland compiler, I can't work out how to reference it from the C# .Net project. DllImport fails with a BadImageFormatException. Googling on this exception indicates that most people encounter this problem when compiling a 64-bit capable program and loading something 32-bit into it. Thing is, I'm reasonably sure I'm generating 16-bit DLLs, and there seems to be no workaround for this.

I can download the newer Borland 5 compiler which has a 32-bit compiler and linker, but I'm still getting the same issue, so perhaps I have something wrong there too.

This is my C# calling code

[DllImport( "C:\\NSDB\\BorlandDLL\\BorlandDLL.dll", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl )]
static extern int Version();

public frmHelpAbout()
{
    InitializeComponent();

    lblIssueVersion.Text =  + Version();
}

This is my DLL code

int Version()
{
    return 93;
}

My compiler flags and linker flags are all complete guesswork - I'm hoping that this is my main problem

I noticed my DLL code is not decorated with anything like __stdcall, extern "C" or whatever. I can't seem to find the correct set of symbols that Borland C++ 3.0 understands to force the kind of calling conventions I need.

So, the questions:

1) Will DllImport ever be able to work with code generated from Borland C++ 3.0 1b) If not, will I be able to port the code to work with the Borland C+ 5.5.1 compiler, and get DllImport to work with that?

2) Can I turn the problem around? If I ported the DLL code into .NET, would I ever be able to get the old Borland code to call it?

3) Do you have any other innovative solutions that will let me simply extract the code I need from this old Borland project?

A: 

.net will call COM and can be called as COM quite happily (for a suitably COM-adjusted value of happy), so if the old native code provides a suitable COM interface you could try using that directly (but that would need to be using a 32-bit build).

If you don't need everything to be in the one process, an alternative approach would be to build the code as a C++/CLI assembly and as a Borland DLL (if you have .c files, then you will need .cpp files that just #include the .c file in the .net project).

Steve Gilham
I'm sorry, I really don't understand your post.The old code is just a C application. It's not split into libraries or anything - it certainly doesn't provide a COM interface. I wish to extract a useful part of this code and leave behind all of the UI code. I must call the rules engine from new C# code, and I must still call the rules engine from the old old Borland code.Should I look further into COM (I've never really understood COM, though seen the acronym a lot)? Where do you start?I like the idea of having code which builds under either compiler, but it doesn't sound easy...
Paul Smith
A: 

If you're using both 32bit .NET and 32bit C-DLL you should not have a problem. I'm almost 100% sure that you can not call 16bit code from a 32bit application easily (though I think I've seen solutions that do that - the word "thunking" comes to my mind here?).

If both .NET and DLL are 32bit, you should be alright with what you're doing above, but I remember that there was something about Borland DLLs which made them kind of incompatible with other "normal" C-DLLs.

The answer by Steve Gilham about COM can be ignored I think, as COM is neither necessary nor a good option in your case.

Thorsten Dittmar
+1  A: 

As far as I know, DllImport will only work for unmanaged dlls that are the same word size as the .Net app. E.g. DllImport in a 64-bit .Net app will only work on 64-bit dlls, a 32-bit .Net app can only load 32-bit dlls, etc. I also don't think it's possible to get DllImport to load a 16-bit dll.

Some possible solutions come to mind:

  1. Steve mentioned using COM. If you want to keep your .Net app in 64-bit, you could use COM to make things work like this: recompile your C code as a 32-bit dll, use .Net to write a 32-bit COM wrapper for that dll, then have your 64-bit .Net app call the 32-bit COM server, which would in turn call your 32-bit dll. MSDN has some info on interoperating with unmanaged code.

  2. Compile both your dll and .Net app for 32-bits. DllImport should be able to load the dll then. (You might need to wrap your C code in extern "C", and run the TDUMP or DUMPBIN utilities on the dll to check for name mangling).

  3. If you have all of the C source code, can you just forget about the Borland compiler and build the code with Visual Studio's C++ compiler?

Chris R. Timmons
I don't think I can do 3 - for now I have to keep the existing program working the way it is - and that uses Borland's UI libraries for the console.I have some code I'm coliming with Borland: extern "C"int __declspec(dllexport) _stdcall DoAdd(int i, int j){ return i+j;}Even compiling this with bcc32 (which I assume is a 32-bit compiler!) and linking with ilink32, I still can't get the resulting DLL to be loadable.How do I know whether or not the generated DLL is really 32 bit?
Paul Smith
I must have had something in the compiler options wrong. Using bcc32 with the -WD option generates a DLL that's loadable.
Paul Smith