## 在VB中如何调用C++Builder创建的DLL ### 合肥电子工程学院计算中心 李 强 ---- C++Builder具有强大的创建Dynamic Link Library 的能力。许多C++Builderr的书藉在创建使用DLL的章节中直接引用的联机文档中的例子。但在Visual C++和VB中直接调用该示例生成的DLL却出现了一些问题，现在我们结合在VB中的调用给出解决方法。示例代码如下所示：
    //////////////////////////

              // Mydll.cpp ////////////////////////// double dblValue(double); double

              halfValue(double); extern __declspec(dllexport) double changeValue(double,

              bool); double dblValue(double value) { return value * value; }; double

              halfValue(double value) { return value / 2.0; } double changeValue(double

              value, bool whichOp) { return whichOp ? dblValue(value) : halfValue(value);

              }
---- 对于外部调用函数加入了__declspec(dllexport)修饰成分，这和Visual C++是相同的，说明该函数将自动从DLL中导出，并对任何调用程序可用。然后，对上述代码在C++Builder环境中编译链接生成Mydll.DLL和Mydll.Lib，并将Mydll.DLL拷入Windows\system目录下(由于VB默认的查找DLL的目录为Windows\system)。 ---- 在VB5.0中新建一个应用，并添加一个模块，在模块中将函数调用说明如下：
    Declare Function changeValue Lib "mydll" (ByVal Value As Double,

              ByVal WhichOp As Boolean) As Double
---- 然后在窗体的一个按钮的Click事件中调用changeValue，对该函数进行测试。测试代码如下：
     Dim aa As Double

              aa = changeValue(10,True)
---- 实际运行中出现了“找不到DLL入口点changeValue in MyDll”的错误信息。 ---- 这时利用资源管理中的快速查看功能查看Mydll.DLL，在Export Table中有关信息如下：
      Ordinal       EntryPoint        Name

      0000         00013c4      @changeValue$qd4bool
---- 发现changeValue函数除了函数名外之外前后还有@、$等附加字符。查阅有关资料得知这是由于编译器对C++名字的修整造成的，由于Microsoft的Visual C++和Borland的C++ Builder的修整方式不同，在分别修整C++名字的时候，对于相同的函数当然就不会出现相同的名字。好再C++语言通过从系统内定义的函数和对象中删除修整，从而有效地解决这一问题。 ---- 将语句extern “C” 放置在程序中的代码块内，编译器就将不会修整这块代码。这时将Mydll.cpp有关代码修改如下：
    extern “C” __declspec(dllexport) double changeValue(double, bool);
---- 再次查看重新生成的Mydll.DLL，这时Export table中的有关信息如下：
     Ordinal EntryPoint Name 0000 00013c4 _changeValue
---- @、$等字符没有了，但在函数名多了一条”＿”线。将Mydll.DLL重新拷入windows\system目录下，并在VB的模块中修改调用说明如下：
    Declare Function changeValue Lib "mydll" Alias “_changeValue” (ByVal

              Value As Double, ByVal WhichOp As Boolean) As Double
---- 运行VB测试程序,出现”DLL 调用约定错误”的错误提示信息。说明changeValue找到了，只是调用约定不对。我们知道调用约定有__fastcall、__pascal、__stdcall、__cdecl四种方式，而在C++Builder中默认调用约定为__cdecl方式，而VB中调用约定为__stdcall方式。 ---- 再将Mydll.cpp的代码修改如下：
    extern

              “C”__declspec(dllexport) double __stdcall changeValue(double, bool);

              …… double __stdcall changeValue(double value, bool whichOp) { return

              whichOp ? dblValue(value) : halfValue(value); } ……
---- 这时查看重新编译链接生成的Mydll.DLL，Export table中的有关信息如下：
      Ordinal       EntryPoint        Name

      0000         00013c4       changeValue
---- 发现函数名前的“＿”线也没有，再次修改VB中调用说明如下：
    Declare

              Function changeValue Lib "mydll" (ByVal Value As Double, ByVal WhichOp

              As Boolean) As Double
---- 运行测试程序，运行结果正确。 ---- 后又将__stdcall调用约定方式改__pascal调用约定方式，运行结果同样正确，但改为__fastcall调用约定方式不行。 ---- 上面所讨论的解决方法不仅适用VB，该方法同样适样Visual C++，这样使Visual C++和C++ Builder 不同编译器生成的DLL可以互相兼容。