Using a Visual C++ DLL in old Borland C? - c++

I've got to support an old app written in C using the old Borland Compiler (BC 5).
Unfortunately the old TCP/IP library that we'd used is starting to show it's age and is having problems with Vista & Win7 machines.
I have a new library of functions available for MS Visual C++, and I'd like to use that to make a DLL that would be callable from the Borland C.
So, I have 2 issues:
1) how to make a Visual C++ DLL callable from a Borland C program, and
2) if it is callable, how to call the C++ functions from plain old C?
Ideally, the entire project should be converted to Visual C, but there a lot of legacy features that'll make that project a major undertaking! I'm looking for a quick patch to keep it alive for a while longer :)
Steve

Write a DLL using Visual C++ that exposes its interface as Windows STDCALL C functions. Windows API functions are done similarly. Those functions you expose in the interface will perform the functions you need to replace in your program. Inside the DLL, call the new MS VC++ library with abandon.
So to get a function that is callable from C and uses STDCALL stack protocol do something like this:
extern "C" int __stdcall foo();
you'll also have to add information to export the function from the DLL. You might do this explicitly in the declaration as such:
extern "C" __declspec(dllexport) int __stdcall foo();
But you'll need a separate header file for use in your BorlandC code (which probably has different syntax for specifying the DLL import part and the STDCALL part). In Visual C++ the declaration you'd use in the client would look something like:
extern "C" __declspec(dllimport) int __stdcall foo();

You can create Borland OMF import libaries with Borland's IMPLIB utility: IMPLIB -a "whatever.omf" "whatever.dll", where the DLL file is that created by MSVC.
The -a option is for Microsoft compatibility. The generated OMF (Borland's import library file format), combined with a header file that specifies the exported functions and their calling convention(s) should work... (I believe IMPLIB was around in C++ Builder 5.)
http://docs.embarcadero.com/products/rad_studio/radstudio2007/RS2007_helpupdates/HUpdate4/EN/html/devwin32/implib_xml.html

Related

How to import the C static Libraries in windows forms application vc++

I have created one static "C" library using VS.
I am using the same library file for another VS console C application its working fine but when I am working with windows forms app it's not working.
Referred so many queries in this forum but didn't get the Help.
Is there any naming conventions to call the static library functions from the Windows forms Managed c++ ?
Getting Errors Like this
error LNK2028: unresolved token (0A000032) "enum STATUS __clrcall
xyz(unsigned char)" (?xyz##$$FYM?AW4STATUS##E#Z) referenced in
function
__catch$?button3_Click#Form1#Myapp##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z$0
But I should use the same static library for both console and windows application.
The linker error message gives a strong hint what it going wrong. Note the __clrcall calling convention for the undefined symbol, it tells you that the compiler thinks that these are "CLR" functions. Managed code, of course they are not, they are __cdecl. There's more, the names are also mangled. Note the "##$$FYM?AW4STATUS##E#Z" curses in the name. Which tells you that the compiler thinks they were written in C++ instead of C.
You'll have to explicitly tell the compiler about this, the .h file isn't compatible enough. Which you do like this in your C++/CLI source code file:
#pragma managed(push, off)
extern "C" {
#include "yadayada.h"
}
#pragma managed(pop)
The #pragmas temporarily turn off managed code compilation mode so the compiler will now assume these are unmanaged function declarations. The extern "C" {} wrap around the #include tells the compiler that the .h file contains C declarations.

What is dllspec(dllimport) and dllspec(dllexport) means

After googling, i came to know that Dllimport makes the function available for other modules,
is it mandatory to declare function with extern "c" identifier?
Also, Dllexport means, Dll itself uses the function while compiling it says. so by default all
functions present in DLL are dllexport?
__declspec(dllexport) exports a symbol. It makes it available from outside a DLL.
__declspec(dllimport) imports a symbol. It practically says "this symbol is not defined in this application, it needs to be imported from a DLL file".
You don't have to declare it with extern "C". If you don't use extern "C", then the symbol will be exported as a C++ symbol, and you will only be able to call it from C++ (and languages that support calling C++ DLLs). If you use extern "C", then the symbol will be exported as a C symbol, and you will be able to call it from languages that support caling C DLLs.
If you want to use your DLL in C#, you will need to use extern "C".
Here is an excellent tutorial that shows you how to use a C++ DLL in C#: How to marshal a C++ class. I have used solution A in many projects at work.
Also, here is a short tutorial on how you can use a C++ DLL in another C++ application: How to create and use DLL in C++.
No -- dllexport means you're exporting it from the DLL (or from an executable) so that other modules (DLLs or executables) can use that function.
dllimport is used to declare a function that's implemented in a DLL (or, again, executable).
So, in a typical case, you'll have something like:
#ifdef BUILDDLL
#define DLL declspec(dllexport)
#else
#define DLL declspec(dllimport)
#endif
Then each public function the DLL will be marked as DLL:
DLL int dosomething(int);
Then, when you're building the DLL, you'll define BUILDDLL, to have all those functions marked as dllexport. Otherwise, you'll include the same header in client code that needs to use the function(s). It won't define BUILDDLL, so they'll all be marked as dllimport instead, so when it comes to link time, it'll create a link to that DLL instead of trying to satisfy those functions from someplace like the standard library.
It also means that entries (in the form of static import and export tables) are created (by the linker) in the exe, dll..files, which document the dependencies between a provider and a consumer.

Old c code to ATL/COM dll

I have an old c dll that I want to convert to a COM server.
It only exposes one function.
This is what I have done:
I created an ATL project in VS 2010 added a simple ATL object with a wrapper function.
I added the c sources and headers
In the wrapper function I call the c function, I added the full function prototype as described in http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.5.
The following error appears:
Unresolved external symbol referenced in function
I tried everything.
Any idea?
You need to use extern "C" when including the c-source:
extern "C" {
#include "header.h"
}
You might try compile the c dll to a regular win32 dll, then calling it from you COM dll through a wrapper. You would need 2 dlls, but if the original DLL will compile fine, you should be able to use it from COM.

Problem with importing DLL into Inno Setup

I am importing an C++ DLL in an Inno Setup install script. The DLL code is as follows:
void __stdcall SetFbParam(
char *dbFileName,char *dbTableName,char *dbParamName,char *dbParamValue) {
// of no use here and doesn't change anything
}
In the Inno Setup, I import it using
procedure FBset(dbFileName,dbTableName,dbParamName,dbParamValue: String;);
external 'SetFbParam#files:MyDll.dll stdcall setuponly';
However, I always get a runtime error during launch of the installer, saying that it cannot import my dll. I tried it with various calling conventions, but it always fails.
If it's of any importance, I'm running Win7 x64 with UAC on (the installer requests rights elevation and crashes after that).
The exact message is:
Error
Runtime error (at -1:0):
Cannot import
dll:C:\Users\Nevod\AppData\Local\Temp\is-6LOEC.tmp\MyDll.dll
The dll is there.
Thanks!
Is MyDll.dll 32-bit?
Does MyDll.dll depend on any other DLLs in the same directory? If so, you need to list the name(s) of those DLLs after MyDll.dll to ensure that they are extracted before MyDll.dll is loaded, and you likely need the loadwithalteredsearchpath option as well. Example from the help:
procedure ADllFunc(hWnd: Integer; lpText, lpCaption: String; uType: Cardinal);
// A.dll depends on B.dll
external 'ADllFunc#files:A.dll,B.dll stdcall loadwithalteredsearchpath';
(I know it is old but maybe some other hits this one too)
Most probably the name of the function is mangled in the C++ DLL. I had the same problem and I was able to solve it by recompiling the dll. In short:
If you export from C++ something like:
void __stdcall foo()
you will get a function called (Visual Studio):
?foo##YGXXZ
To prevent name mangling you should use extern "C" directive. Example (Visual Studio)
extern "C" __declspec( dllexport ) void __stdcall foo()
However I have found that Visual Studio will continue to mangle and you get something like:
_foo#0
The sole way I was able to get clean names is explained here:
C++ DLL Export: Decorated/Mangled names
And the culprit is indeed __stdcall. If you remove that from your declaration:
extern "C" __declspec( dllexport ) void foo()
you will again get a clean export, even without a DEF file. IMO this should be good enough, as the code above declares a "C" exported function and the default calling convention for C is stdcall. However I haven't had the time and disposition to validate this as adding a DEF file is way easier than navigating asm code and check stack pointers :)
In order to use DLLs in Inno Setup's [Code] section please make sure:
DLL is in 32 bit mode (even if the installer is built for 64bit and is running in 64bit mode)
exported functions have
extern "C" __declspec( dllexport )
modifier
use cdecl calling convention because stdcall mangles name (https://learn.microsoft.com/en-us/cpp/cpp/stdcall). Of course it is possible to specify mangled name in Inno Setup import statement. But it seems easier to just use cdecl.
As mentioned in other answers, do not forget to embed all dependencies of your DLL. Though if it is your DLL, better might be to get rid of (or at least reduce) the dependencies.
For example when building C++ DLL in Visual Studio, link the runtime statically, not dynamically.
In project Properties, go to C/C++ > Code Generation > Runtime Library and select Multi-threaded (not DLL).
There are also tools that can embed other external dependencies.
See Embedding DLLs in a compiled executable

How to import external dll library to Borland C++ 6?

I build an application in Borland C++ 6 and I'd like to import external, non Borland library (FFTW, to be exact, http://www.fftw.org).
I have downloaded the fftw dll file, used the implib.exe program to build a lib file known to Borland, included fftw.h in source and copied fftw.h to Borland/include, fftw.lib to Borland/lib and .h, .dll and .lib files to my project folder.
Unfortunately I get several linker errors, which claims:
Unresolved external '{name of the FFTW function}' referenced from {name of the source file}
What do I do wrong?
I'm just telling from a similar story how I managed to get it to work...
There was a DLL that worked (was being sucessfully imported) with Delphi 7, VB.NET and Java. I wanted to make a program with Borland C++ Builder 6 with it. I had the function prototypes and the exact declarations that made the import on those languages. Reasonable?
I thought it would be easy, but I stucked on many dead ends without sucess, with step by step "blind" guides that didn't worked for me. And the IDE or command outputs not helping either.
After a few days I tried (from question 4599357, although the DLL isn't in Visual C++):
using "implib" without "-a" and
having the prototypes declared like this:
extern "C" __declspec(dllimport) __stdcall int someDll_someFunction(someTypes someArgs, ...);
Note that the normal function prototype is at the end. If you have the "normal" prototypes, just add "extern "C" __declspec(dllimport) __stdcall" before them to your source code or header file. :) And I only have functions that return "int", this is why I put "int" there.
I think you're only missing one step... add the .lib file that implib created to your project.
Are you sure that Borland is doing proper name-mangling of the external functions, and that the header has been surrounded with extern "c" {}? And are you sure that Borland is indeed trying to link with the .lib file? Make sure the compiler has the verbose option set.
If that doesn't work, why don't you build FFTW from source instead of using a DLL?