• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 363
  • Last Modified:

How to use DLL again


Hi,

I have a Borland C++ DLL "testapi.dll", now I want to use it in Visual C++ project. I did as following:

1)use "impdef testapi testapi.dll" got a "testapi.def" (The  "impdef" is a Broland command).
2)use "\msdev\bin\lib: /def:testapi.def" got a "testapi.lib"

Then I added the testapi.lib file into my project. The problem is:

The funtion I defined in the testapi.dll is "CreatTestWindow", when I built the VC++ project, there is a linker error, "unresolved function _CreatTestWindow". I don't know why there is an extra "_". Does that because my conversion is not correct?

Thanks.  
0
Gina060497
Asked:
Gina060497
  • 5
  • 4
1 Solution
 
chensuCommented:
In your testapi.h, you may declare the function like this:
int CreatTestWindow(DWORD dwParam);

Your project contains the CPP files, so it uses C++ linkage by default but your testapi.dll uses C linkage. Change your declaration to:

extern "C" int CreatTestWindow(DWORD dwParam);

Or, as most of the standard header files,

#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
}
#endif

0
 
Gina060497Author Commented:
Thanks very much for Chensu's help. Actually I already defined " extern "C" int CreatTestWindow(DWORD dwParam)", I also used
                  #ifdef __cplusplus
                  extern "C" {
                  #endif
But the error is still there.

Now my testapi.dll contains the CPP files, but my project only uses C files. I already added
                  #ifdef __cplusplus
                  extern "C" {
                  #endif
into my project head files.

When I view the "testapi.def", the function "CreatTestWindow" is there as an export function. But when I view the "testapi.lib", the function changed to "_CreatTestWindow". Can anyone tell me what happened?

Thank you very much for your help.

 
0
 
chensuCommented:
When you built your testapi.dll, did you add extern "C"? You need to build the DLL using C linkage.

The reason that the function is changed to "_CreatTestWindow" is that the compiler and linker use this convention for internal use. It always adds the extra "_" before the function names.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
Gina060497Author Commented:
Yes, I added extern "C" when I built "testapi.dll". The error message is "unresolved function _CreatTestWindow@20". Then I added "CreatTestWindow@20" into my "testapi.def", used "\msdev\bin\lib /def:testapi.def" to recreat the testapi.lib. There is not liker error after that. But the problem is I can't call the function "CreatTestWindow", whenever I called it in my VC project, there are some problems. The reason seems still because of the Borland C++ "testapi.dll".

Thank you very much for your help.

 
0
 
chensuCommented:
I think the problem is related to the calling convention. Add WINAPI to the function prototype (for the DLL and the VC project) to use the pascal calling convention on both sides.

extern "C" int WINAPI CreatTestWindow(DWORD dwParam);

And, you may need to add a space between CreatTestWindow and @20.

BTW, I am not sure if Borland C++ define the WINAPI macro. If not, you can check Microsoft version.
0
 
Gina060497Author Commented:
Here is my "testapi.cpp" and "testapi.h": (and also,when I changed "CreatTestWindow@20" to "CreatTestWindow @20", the error of "unresolved function "CreatTestWindow@20" comes again).

I saw a note in the microsoft knowledge base Q131313:
"This method (import Libraries without .objs or source) may not work with DLLs generated with non_Microsofe development tools." Could that be reason of the problem?

Thanks

TESTAPI.CPP
======================
#include <owl/window.h>
#include <owl/module.h>
#include <windows.h>

static TModule* g_ResMod;
static TModule* g_BwccMod;

#ifdef WIN32
      BOOL WINAPI
      DllEntryPoint(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
      {
            if (dwReason == DLL_PROCESS_ATTACH)
            {
                  //if (!g_ResMod) {
                  //      g_ResMod = new TModule(0, hInstance);
                  //      g_BwccMod =  new TModule ("bwcc.dll");
                  //}
            }
            else
            if (dwReason == DLL_PROCESS_DETACH)
            {
            }

            return 1;  // ok
      }
#else

extern "C"
int FAR PASCAL LibMain (HINSTANCE hInstance, WORD wDataSeg, WORD cbHeapSize, LPSTR lpCmdLine) {
       if (!g_ResMod) {
            g_ResMod = new TModule(0, hInstance);
            g_BwccMod =  new TModule ("bwcc.dll");
      }
      if (cbHeapSize > 0)
            UnlockData(0);
       return true;
}

#endif

static TWindow* g_pwndParent = 0;
static TWindow* g_testWnd = 0;

extern "C" void WINAPI _export Function() {

}

extern "C"
//void  _export CreateTestWindow() {
 void WINAPI _export CreateTestWindow(HWND hwndParent, WORD x, WORD y, int wd, int ht) {

/*      g_pwndParent = new TWindow ( hwndParent, g_ResMod );
      g_testWnd = new TWindow ( g_pwndParent, 0, g_ResMod );
      g_testWnd->Attr.Style |= WS_CHILD | WS_VISIBLE | WS_BORDER;
      g_testWnd->Attr.X = 0;
      g_testWnd->Attr.Y = 0;
      g_testWnd->Attr.W = 100;
      g_testWnd->Attr.H = 100;

   */

      MessageBox ( NULL, "CreateTestWindow called\n", "TestApi", MB_OK );

   }

extern "C"
//void _export DestroyTestWindow() {
void WINAPI _export DestroyTestWindow() {
/*
      g_pwndParent->Destroy();
      delete g_pwndParent;

   */

      MessageBox ( NULL, "DestroyTestWindow called\n", "TestApi", MB_OK );

}

TESTAPI.H
==========================
#ifndef _TESTAPI_H_
#define _TESTAPI_H_

#ifdef __cplusplus
extern "C"
{
#endif

void WINAPI _export CreateTestWindow(HWND hwndParent, WORD x, WORD y, int wd, int ht);

#ifdef __cplusplus
};
#endif

#endif      //_TESTAPI_H_
0
 
chensuCommented:
Hi, I am here again.

Yes, I think that is the reason. ("This method (import Libraries without .objs or source) may not work with DLLs generated with non_Microsofe development tools.") Borland C++ 5.01 has the implib.exe for 32-bit DLLs. Try that one.
0
 
Gina060497Author Commented:
I used "implib.exe" to import the testapi.lib. The error was " testapi.lib: fatal error LNK1136: invalid or corrupt file." I tried again using "\bc5\bin\implib testapi testapi.dll" just now, still the same error.

"Could anyone tell me how to use Borland C++ DLL files in VC 4.00?" :)

Thank you very much for your help.

Gina



0
 
md041797Commented:
This is from Ron Burk's column in Win Dev Jrn, Aug 96:

VC++'s Missing Import Utility
Yet another new inconvenience that the 32-bit Visual C++ offers is the inability to create import libraries directly from DLLs. In the past, Microsoft (like all other Windows compiler vendors) provided a utility that, given an arbitrary DLL, would create an import library so you could link implicitly with that DLL. Incredibly, the 32-bit version of Visual C++ no longer offers such a utility; Microsoft's 32-bit link.exe can create an import library when it links your object code, but can't create an import library from just the DLL itself. In a Knowledge Base note (PSS ID Number Q131313), Microsoft offers two alternatives. One only works with __cdecl functions. The other requires that you to make a dummy DLL with Visual C++ that has stubs for all the entry points in the target DLL, and then generate an import library from that fake DLL of stubs. Customers will not be happy if you hand them a DLL and tell them to jump through these hoops to make it work with Visual C++.
 
If you must ship a DLL that can be implicitly linked with Microsoft's compiler, it looks like you actually have to buy a copy of Visual C++ and use it just to generate a Microsoft import library (unless you care little for your end user's convenience). As you might expect, Borland C++ still includes a utility to generate an import library from a DLL. For example, if someone hands you a Microsoft-compiled DLL called dll.dll, all you have to do is type
 
implib dll.lib dll.dll
 
to create a Borland import library for it. Borland and Microsoft use incompatible formats for their import libraries, so the Borland .lib file will not work with Microsoft's compiler or vice versa.


MS Knowledge Base is at www.microsoft.com/kb.
Hope this helps.
0
 
Gina060497Author Commented:
Thanks much for help.

Gina
0

Featured Post

[Webinar] Improve your customer journey

A positive customer journey is important in attracting and retaining business. To improve this experience, you can use Google Maps APIs to increase checkout conversions, boost user engagement, and optimize order fulfillment. Learn how in this webinar presented by Dito.

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now