• BCB编写DLL


    一.注意:
    创建动态链接库时,如果想你创建的动态链接库并非只用于Borland开发工具,那么就需要遵循发下规则:
    (1).在导出函数的返回值和参数中不要使用Borland特有的数据类型和结构体,如AnsiString之类,请使用C/C++标准的数据类型或使用 C/C++标准数据类型定义的结构体(特别不要使用String数据类型,BCB DLL向导生成的DLL工程文件中大篇幅的说明就是对此的说明,请自己查阅);
    (2).请使用extern "C"命名约定,这样,生成的DLL中的导出函数,就不会使用C++的命名约定,而是使用的C命名约定,即导出函数不会名字分解,而是和你定义的函数相同;
    (3).导出函数请使用WIN32 API的调用方式__stdcall(即WINAPI)或VC与BorlandC++的调用约定__cdecl,不要使用Borland特有的__fastcall调用约定,否则只有Borland开发工具才可以使用这些动态链接库;
    二.实例:
    (1).导出函数(不使用VCL)
    使用BCB建立DLL向导来建立一个工程,选择不使用VCL,代码如下:
    //---------------------------------------------------------------------------
    #include 
    //---------------------------------------------------------------------------
    //    Important note about DLL memory management when your DLL uses the
    //    static version of the RunTime Library:
    //
    //    If your DLL exports any functions that pass String objects (or structs/
    //    classes containing nested Strings) as parameter or function results,
    //    you will need to add the library MEMMGR.LIB to both the DLL project and
    //    any other projects that use the DLL.   You will also need to use MEMMGR.LIB
    //    if any other projects which use the DLL will be performing new or delete
    //    operations on any non-TObject-derived classes which are exported from the
    //    DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
    //    EXE's to use the BORLNDMM.DLL as their memory manager.   In these cases,
    //    the file BORLNDMM.DLL should be deployed along with your DLL.
    //
    //    To avoid using BORLNDMM.DLL, pass string information using "char *" or
    //    ShortString parameters.
    //
    //    If your DLL uses the dynamic version of the RTL, you do not need to
    //    explicitly add MEMMGR.LIB as this will be done implicitly for you
    //---------------------------------------------------------------------------
    #pragma argsused
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
         return 1;
    }
    //---------------------------------------------------------------------------
    extern "C" __declspec(dllexport) int __stdcall Calc(int a, int b) //导出函数
    {
         return a+b;
    }
    //---------------------------------------------------------------------------
    保存工程为DLLs,编译,就会在工程目录下生成DLLs.dll(大小应该是8K),同时还会自动在同一目录下生成DLLs.lib静态库,如果没有生成,请自己手动使用implib.exe工具生成(使用方法见本文说明)。
    (2).导出函数(使用VCL)
    使用BCB DLL向导建立一个工程,选择使用VCL支持,新建立一个窗体(采用默认名称TForm1)存为Unit1.cpp,设置窗体大小为一般OKCANCEL 对框的大小(这里设为277*119),在窗体上添加两个按钮:Button1标签为"确定",ModalResult为mrOk,Button2标签为 "取消",ModalResult为mrCancel;
    然后在DLL主程序中引用刚才建立的窗体,并添加导出函数,代码如下:
    //---------------------------------------------------------------------------
    #include 
    #include 
    #pragma hdrstop
    //---------------------------------------------------------------------------
    //    Important note about DLL memory management when your DLL uses the
    //    static version of the RunTime Library:
    //
    //    If your DLL exports any functions that pass String objects (or structs/
    //    classes containing nested Strings) as parameter or function results,
    //    you will need to add the library MEMMGR.LIB to both the DLL project and
    //    any other projects that use the DLL.   You will also need to use MEMMGR.LIB
    //    if any other projects which use the DLL will be performing new or delete
    //    operations on any non-TObject-derived classes which are exported from the
    //    DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
    //    EXE's to use the BORLNDMM.DLL as their memory manager.   In these cases,
    //    the file BORLNDMM.DLL should be deployed along with your DLL.
    //
    //    To avoid using BORLNDMM.DLL, pass string information using "char *" or
    //    ShortString parameters.
    //
    //    If your DLL uses the dynamic version of the RTL, you do not need to
    //    explicitly add MEMMGR.LIB as this will be done implicitly for you
    //---------------------------------------------------------------------------
    #include "Unit.h" //引用设计的窗体
    #pragma argsused
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
         return 1;
    }
    //---------------------------------------------------------------------------
    extern "C" __declspec(dllexport) int __stdcall UserClick(void) //导出函数
    {
         TForm1 *Form1 = new TForm1(NULL);
         if(Form1->ShowModal() == mrOk) {
             delete Form1;
             return 1;
         } else {
             delete Form1;
             return 0;
         }
    }
    //--------------------------------------------------------------------------- 
    保存工程为DLLs,编译,就会在工程目录下生成DLLs.dll,同时还会自动在同一目录下生成DLLs.lib静态库,如果没有生成,请自己手动使用implib.exe工具生成。
    (3).导出类
    使用BCB建立DLL向导来建立一个工程,选择不使用VCL(本例不使用VCL,是否支持VCL是视你自己的应用而定),代码如下:
    //---------------------------------------------------------------------------
    #include 
    //---------------------------------------------------------------------------
    //    Important note about DLL memory management when your DLL uses the
    //    static version of the RunTime Library:
    //
    //    If your DLL exports any functions that pass String objects (or structs/
    //    classes containing nested Strings) as parameter or function results,
    //    you will need to add the library MEMMGR.LIB to both the DLL project and
    //    any other projects that use the DLL.   You will also need to use MEMMGR.LIB
    //    if any other projects which use the DLL will be performing new or delete
    //    operations on any non-TObject-derived classes which are exported from the
    //    DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
    //    EXE's to use the BORLNDMM.DLL as their memory manager.   In these cases,
    //    the file BORLNDMM.DLL should be deployed along with your DLL.
    //
    //    To avoid using BORLNDMM.DLL, pass string information using "char *" or
    //    ShortString parameters.
    //
    //    If your DLL uses the dynamic version of the RTL, you do not need to
    //    explicitly add MEMMGR.LIB as this will be done implicitly for you
    //---------------------------------------------------------------------------
    #pragma argsused
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
         return 1;
    }
    //---------------------------------------------------------------------------
    __declspec(dllexport) __stdcall class TTest{     //声明导出类
         int a,b;
    public:
         void __stdcall SetValue(int x, int y);
         int __stdcall Calc(void);
    };
    //---------------------------------------------------------------------------
    void __stdcall TTest::SetValue(int x, int y)     //类的实现
    {
         this->a = x;
         this->b = y;
    }
    //---------------------------------------------------------------------------
    int __stdcall TTest::Calc(void) //类的实现
    {
         return this->a + this->b;
    }
    //---------------------------------------------------------------------------

    保存工程为DLLs,编译,就会在工程目录下生成DLLs.dll,同时还会自动在同一目录下生成DLLs.lib静态库,如果没有生成,请自己手动使用implib.exe工具生成。
    注意,并非所有的代码都需要在工程DLL主文件中写,导出函数和类等都可以在其它单元中设计,然后在主文件中#include即可,看自己的习惯,当然了,一个巨大的DLL工程,不可能写在一个文件中的。
    (4).使用(1)创建的DLL
    新建一个工程。
    [1].静态调用:
    向工程中添加(1)中生成的静态库DLLs.lib,然后在.h中添加导出函数的定义,如下:
    extern "C" __declspec(dllimport) int __stdcall Calc(int,int); //导出DLL中函数
    然后就可以在这个单元中使用int __stdcall Calc(int,int)这个函数了,如:
    ShowMessage(IntToStr(Calc(5,10));
    [2].动态调用
    不需要添加静态库.lib文件,只要在需要调用时才载入DLL,如下:
         HINSTANCE Hdl;
         int __stdcall (*Calc)(int,int); //定义函数原型
         Hdl = ::LoadLibrary("DLLs.dll"); //载入DLL
         if(Hdl != NULL) {
             Calc = (int __stdcall (*)(int,int))::GetProcAddress(Hdl,"Calc"); //获取函数入口地址
             if(Calc != NULL) {
                 ShowMessage(IntToStr(Calc(5,10))); //调用DLL中函数
             } else {
                 ShowMessage("不能找到函数入口!");
             }
             ::FreeLibrary(Hdl); //一定不要忘记调用完毕后释放DLL
         } else {
             ShowMessage("不能载入DLL!");
         }
    (5).使用(2)创建的DLL
    [1].静态调用:
    向工程中添加(2)中生成的静态库DLLs.lib,然后在.h中添加导出函数的定义,如下:
    extern "C" __declspec(dllimport) int __stdcall UserClick(void); //导出DLL中函数
    然后就可以在这个单元中使用int __stdcall UserClick(void)这个函数了,如:
         if(UserClick()) {
             ShowMessage("用户点击“确定”");
         } else {
             ShowMessage("用户点击“取消”或直接关闭");
         }
    [2].动态调用
    不需要添加静态库.lib文件,只要在需要调用时才载入DLL,如下:
         HINSTANCE Hdl;
         int __stdcall (*UserClick)(void);
         Hdl = ::LoadLibrary("DLLs.dll");
         if(Hdl != NULL) {
             UserClick = (int __stdcall (*)(void))::GetProcAddress(Hdl,"UserClick");
             if(UserClick != NULL) {
                 if(UserClick()) {
                     ShowMessage("用户点击“确定”");
                 } else {
                     ShowMessage("用户点击“取消”或直接关闭");
                 }
             } else {
                 ShowMessage("不能找到函数入口!");
             }
             ::FreeLibrary(Hdl);
         } else {
             ShowMessage("不能载入DLL!");
         }
    (6).使用(3)创建的DLL
    DLL中导出的类,只能使用表态的方式来调用。本例中的DLL调用方法如下:
    向工程中添加(3)中生成的静态库DLLs.lib,然后在.h中添加导出类的声明,如下:
    __declspec(dllimport) __stdcall class TTest{
         int a,b;
    public:
         void __stdcall SetValue(int x, int y);
         int __stdcall Calc(void);
    };
    然后就可以在这个单元中使用TTest这个类了,如:
         TTest *Inst = new TTest;
         Inst->SetValue(5,10);
         ShowMessage(IntToStr(Inst->Calc()));
         delete Inst;
    三.一些工具:
    (1).impdef.exe
    用法:impdef.exe deffile.def yourdll.dll
    生成指定DLL文件的def文件,可以用它来查看DLL中的函数声明。例如,BCB使用VC的DLL时,可能需要查看一下VC中导出函数的函数名;或者未使用extern "C"调用约定时,可以用它来查看DLL中导出函数的C++命名方式,从而可以正确调用。
    (2).implib.exe
    用法:implib.exe libfile.lib yourdll.dll
    用此工具来生成DLL调用的静态库,用于DLL的静态调用方式。
    (3).vctobpru.exe
    用此工具可以把VC的工程导入到BCB工程中,它自动转换VC的工程文件为BCB工程文件,生成相应的.bpr等文件。
    (4).tdump.exe(VC中为dumpbin.exe)
    用法:tdump.exe [options] [inputfile] [listfile] [options]
    用此工具可以查看DLL中的导出函数声明等等,具体用法请运行tdump.exe(不加参数)。

    ====

    BCB编写DLL终极手册

      一. 编写 DLL

      File/New/Dll 生成 Dll 向导,然后可以添加导出函数和导出类

      导出函数:extern "C" __declspec(dllexport) ExportType FunctionName(Parameter)

      导出类:class __declspec(dllexport) ExportType ClassName{...}

      例子:(说明:只是生成了一个 DLL.dll )

    #include "DllForm.h" // TDllFrm 定义
    
    USERES("Dll.res");
    USEFORM("DllForm.cpp", DllFrm);
    
    class __declspec(dllexport) __stdcall MyDllClass { //导出类
        public:
           MyDllClass();
           void CreateAForm();
           TDllFrm* DllMyForm;
    };
    
    TDllFrm* DllMyForm2;
    extern "C" __declspec(dllexport) __stdcall void CreateFromFunct();//导出函数
    
    //---------------------------------------------------------------------------
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
    {
        return 1;
    }
    //---------------------------------------------------------------------------
    
    MyDllClass::MyDllClass()
    {
    }
    
    void MyDllClass::CreateAForm()
    {
        DllMyForm = new TDllFrm(Application);
        DllMyForm->Show();
    }
    //---------------------------------------------------------------------------
    void __stdcall CreateFromFunct()
    {
        DllMyForm2 = new TDllFrm(Application);
        DllMyForm2->Show();
    }


    二. 静态调用 DLL

      使用 $BCB path\Bin\implib.exe 生成 Lib 文件,加入到工程文件,将该文件拷贝到当前目录,使用 implib MyDll.lib MyDll.dll 生成。

    // Unit1.h // TForm1 定义
    #include "DllForm.h" // TDllFrm 定义
    //---------------------------------------------------------------------------
    
    __declspec(dllimport) class __stdcall MyDllClass {
        public:
            MyDllClass();
            void CreateAForm();
            TDllFrm* DllMyForm;
    }; 
    extern "C" __declspec(dllimport) __stdcall void CreateFromFunct();
    
    class TForm1 : public TForm{}
    
    // Unit1.cpp // TForm1 实现
    void __fastcall TForm1::Button1Click(TObject *Sender)
    { // 导出类实现,导出类只能使用静态方式调用
        DllClass = new MyDllClass();
        DllClass->CreateAForm();    
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button2Click(TObject *Sender)
    { // 导出函数实现
        CreateFromFunct();
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
        delete DllClass;
    }


    三. 动态调用 DLL

    // Unit1.h 
    class TForm1 : public TForm
    {
    
    private: // User declarations
    void (__stdcall *CreateFromFunct)();
    
    }
    
    // Unit1.cpp // TForm1
    HINSTANCE DLLInst = NULL;
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
        if( NULL == DLLInst ) DLLInst = LoadLibrary("DLL.dll"); //上面的 Dll
        if (DLLInst) { 
            CreateFromFunct = (void (__stdcall*)()) GetProcAddress(DLLInst,
                                                        "CreateFromFunct");
            if (CreateFromFunct) CreateFromFunct();
            else ShowMessage("Could not obtain function pointer");
        }
        else ShowMessage("Could not load DLL.dll");
    }
    
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
        if ( DLLInst ) FreeLibrary (DLLInst);
    }


    四. DLL 作为 MDIChild (子窗体) 【只编写动态调用的例子】

      实际上,调用子窗体的 DLL 时,系统只是检查应用程序的 MainForm 是否为 fsMDIForm 的窗体,这样只要把调用程序的 Application 的 Handle 传递给 DLL 的 Application 即可;同时退出 DLL 时也要恢复。

    Application

    // MDIChildPro.cpp // Dll 实现 CPP

    #include "unit1.h" // TForm1 定义
    TApplication *SaveApp = NULL;
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
    {
        if ( (reason==DLL_PROCESS_DETACH) && SaveApp )
            Application = SaveApp ; // 恢复 Application
        return 1;
    }
    
    extern "C" __declspec(dllexport) __stdcall void TestMDIChild(    //1024X768
        TApplication* mainApp,
        LPSTR lpCaption)
    {
        if ( NULL == SaveApp ) // 保存 Application,传递 Application
        {
            SaveApp = Application;
            Application = mainApp;
        }
        // lpCaption 为子窗体的 Caption
        TForm1 *Form1 = new TForm1 ( Application, lpCaption ); 
        Form1->Show();
    }


      注:上面的程序使用 BCB 3.0 编译成功

      五. BCB 调用 VC 编写的 DLL

      1. 名字分解:

      没有名字分解的函数

            TestFunction1 // __cdecl calling convention
            @TestFunction2 // __fastcall calling convention
            TESTFUNCTION3 // __pascal calling convention
            TestFunction4 // __stdcall calling convention

      有名字分解的函数

            @TestFunction1$QV // __cdecl calling convention
            @TestFunction2$qv // __fastcall calling convention
            TESTFUNCTION3$qqrv // __apscal calling convention
            @TestFunction4$qqrv // __stdcall calling convention

      使用 extern "C" 不会分解函数名

      使用 Impdef MyLib.def MyLib.DLL 生成 def 文件查看是否使用了名字分解

      2. 调用约定:

      __cdecl 缺省

      是 Borland C++ 的缺省的 C 格式命名约定,它在标识符前加一下划线,以保留它原来所有的全程标识符。参数按最右边参数优先的原则传递给栈,然后清栈。

            extaern "C" bool __cdecl TestFunction();

      在 def 文件中显示为 TestFunction @1

      注释: @1 表示函数的顺序数,将在“使用别名”时使用。

    百事通



      __pascal Pascal格式

      这时函数名全部变成大写,第一个参数先压栈,然后清栈。

      TESTFUNCTION @1 //def file

      __stdcall 标准调用

      最后一个参数先压栈,然后清栈。

      TestFunction @1 //def file

      __fastcall 把参数传递给寄存器

      第一个参数先压栈,然后清栈。

      @TestFunction @1 //def file

      3. 解决调用约定:

      Microsoft 与 Borland 的 __stdcall 之间的区别是命名方式。 Borland 采用__stdcall 的方式去掉了名字起前的下划线。 Microsoft 则是在前加上下划线,在后加上 @ ,再后跟为栈保留的字节数。字节数取决于参数在栈所占的空间。每一个参数都舍入为 4 的倍数加起来。这种 Miocrosoft 的 DLL 与系统的 DLL 不一样。

      4. 使用别名:

      使用别名的目的是使调用文件 .OBJ 与 DLL 的 .DEF 文件相匹配。如果还没有.DEF 文件,就应该先建一个。然后把 DEF 文件加入 Project。使用别名应不断修改外部错误,如果没有,还需要将 IMPORTS 部分加入 DEF 文件。

            IMPORTS
            TESTFUNCTIOM4 = DLLprj.TestFunction4
            TESTFUNCTIOM5 = DLLprj.WEP @500
            TESTFUNCTIOM6 = DLLprj.GETHOSTBYADDR @51

      这里需要说明的是,调用应用程序的 .OBJ 名与 DLL 的 .DEF 文件名是等价的,而且总是这样。甚至不用考虑调用约定,它会自动匹配。在前面的例子中,函数被说明为 __pascal,因此产生了大写函数名。这样链接程序不会出错。

      5. 动态调用例子

      VC DLL 的代码如下:

    extern "C" __declspec(dllexport) LPSTR __stdcall BCBLoadVCWin32Stdcall()
    {
    static char strRetStdcall[256] = "BCB Load VC_Win32 Dll by __stdcall mode is OK!";
    
    return strRetStdcall;
    }
    
    extern "C" __declspec(dllexport) LPSTR __cdecl BCBLoadVCWin32Cdecl()
    {
    static char strRetCdecl[256] = "BCB Load VC_Win32 Dll by __cdecl mode is OK!";
    
    return strRetCdecl;
    }
    
    extern "C" __declspec(dllexport) LPSTR __fastcall BCBLoadVCWin32Fastcall()
    {
    static char strRetFastcall[256] = "BCB Load VC_Win32 Dll by __fastcall mode is OK!";
    
    return strRetFastcall;
    }


    其实动态调用与调用 BCB 编写的 DLL 没有区别,关键是查看 DLL 的导出函数名字。可以使用 tdump.exe(BCB工具) 或者 dumpbin.exe(VC工具) 查看
         tdump -ee MyDll.dll >1.txt (查看 1.txt 文件即可)

      由于 VC6 不支持 __pascall 方式,下面给出一个三种方式的例子:

    void __fastcall TForm1::btnBLVCWin32DynClick(TObject *Sender)
    {
        /*cmd: tdbump VCWin32.dll >1.txt
    Turbo Dump Version 5.0.16.4 Copyright (c) 1988, 1998 Borland International
                        Display of File VCWIN32.DLL
    
    EXPORT ord:0000='BCBLoadVCWin32Fastcall::'
    EXPORT ord:0001='BCBLoadVCWin32Cdecl'
    EXPORT ord:0002='_BCBLoadVCWin32Stdcall@0'
        */
        if ( !DllInst )
            DllInst = LoadLibrary ( "VCWin32.dll" );
        if ( DllInst )
        {
            BCBLoadVCWin32Stdcall = (LPSTR (__stdcall *) () )
                GetProcAddress ( DllInst, "_BCBLoadVCWin32Stdcall@0" ); //VC Dll
                // GetProcAddress ( DllInst, "BCBLoadVCWin32Stdcall" ); //BCB Dll
            if ( BCBLoadVCWin32Stdcall )
            {
                ShowMessage( BCBLoadVCWin32Stdcall() );
            }
            else ShowMessage ( "Can't find the __stdcall Function!" );
    
            BCBLoadVCWin32Cdecl = (LPSTR (__cdecl *) () )
                GetProcAddress ( DllInst, "BCBLoadVCWin32Cdecl" );
            if ( BCBLoadVCWin32Cdecl )
            {
                ShowMessage( BCBLoadVCWin32Cdecl() );
            }
            else ShowMessage ( "Can't find the __cdecl Function!" );
    
            //Why?不是 'BCBLoadVCWin32Fastcall::',而是 '@BCBLoadVCWin32Fastcall@0'?
            BCBLoadVCWin32Fastcall = (LPSTR (__fastcall *) () )
                //GetProcAddress ( DllInst, "BCBLoadVCWin32Fastcall::" );
                GetProcAddress ( DllInst, "@BCBLoadVCWin32Fastcall@0" );
            if ( BCBLoadVCWin32Fastcall )
            {
                ShowMessage( BCBLoadVCWin32Fastcall() );
            }
            else ShowMessage ( "Can't find the __fastcall Function!" );
        }
        else ShowMessage ( "Can't find the Dll!" );
    }


    6. 静态调用例子

      静态调用有点麻烦,从动态调用中可以知道导出函数的名字,但是直接时(加入 lib 文件到工程文件)

      Linker 提示不能找到函数的实现

      从 4 看出,可以加入 def 文件连接(可以通过 impdef MyDll.def MyDll.dll 获得导出表)。

      建立与 DLL 文件名一样的 def 文件与 lib 文件一起加入到工程文件。

      上面的 DLL(VCWIN32.dll) 的 def 文件为(VCWIN32.def):

    LIBRARY     VCWIN32.DLL

    IMPORTS
        @BCBLoadVCWin32Fastcall     = VCWIN32.@BCBLoadVCWin32Fastcall@0
        _BCBLoadVCWin32Cdecl        = VCWIN32.BCBLoadVCWin32Cdecl
        BCBLoadVCWin32Stdcall       = VCWIN32._BCBLoadVCWin32Stdcall@0

      对应的函数声明和实现如下:

    extern "C" __declspec(dllimport) LPSTR __fastcall BCBLoadVCWin32Fastcall();
    extern "C" __declspec(dllimport) LPSTR __cdecl BCBLoadVCWin32Cdecl();
    extern "C" __declspec(dllimport) LPSTR __stdcall BCBLoadVCWin32Stdcall();

    void __fastcall TfrmStatic::btnLoadDllClick(TObject *Sender)
    {
        ShowMessage ( BCBLoadVCWin32Fastcall() );
        ShowMessage ( BCBLoadVCWin32Cdecl() );
        ShowMessage ( BCBLoadVCWin32Stdcall() );
    }

      注意:在 BCB 5.0 中,可能直接按下 F9 是不能通过 Linker 的,请先 Build 一次。上面的程序使用 BCB 5.0 与 VC6.0 编译成功

    ---------------------------[版权声明]--------------------------- 本博客的技术文章以及程序源码,包括原创,转载和翻译三种类型。部分资料来源于网上,作品的版权属于原创作者所有。凡是在标题处带有“【原创】”标识的随笔、文章等,都为本人根据自己的实际能力所创,其他即为转载。如果您需要转载本博客发布的原创及翻译作品,请注明来源,作者及翻译人等信息,如果本博客发布的内容触犯了您的版权,请来信告诉我,我将马上删除,谢谢合作。

     
  • 相关阅读:
    Java 反射 调用 demo
    Java 使用 DBCP mysql 连接池 做数据库操作
    Java 使用 Dbutils 工具类库 操作mysql
    NodeJs 遍历文件夹内容 上传到服务器.并输出上传记录文件
    Java-JDBC.mysql 工具类 读取本地文件配置
    vue使用axios发送数据请求
    word2vec 理论与实践
    pytorch_SRU(Simple Recurrent Unit)
    Highway Networks Pytorch
    Highway Networks
  • 原文地址:https://www.cnblogs.com/cpprun/p/2660743.html
Copyright © 2020-2023  润新知