dll_lib.cpp

View page source

dll_lib: Example and Test

options

The following subsection of this example sets options that are different from the default options:

    // Example using options that are different from the default options
    std::map< std::string, std::string > options;
# ifdef _MSC_VER
    options["compile"] = "cl /EHs /EHc /c /TC /O2";
# elif CPPAD_LINK_FLAGS_HAS_M32
    options["compile"] = "gcc -c -fPIC -O2 -m32";
# else
    options["compile"] = "gcc -c -fPIC -O2";
# endif

Restrictions

This example is only built and run under the following conditions:

  1. The cmake command determines that the C compiler is gcc, clang, or msvc.

  2. The cmake command determines it is OK to use C++17 features.

  3. The cppad_link_flags do not contain -m32 .

Source

# include <filesystem>
# include <fstream>
# include <vector>
# include <map>
# include <cppad/utility/create_dll_lib.hpp>
# include <cppad/utility/link_dll_lib.hpp>

# if _WIN32
# define DIR_SEP '\\'
# define DLL_EXT ".dll"
# else
# define DIR_SEP '/'
# define DLL_EXT ".so"
# endif

// CALL_CONVENTION, CALL_IMPORT
# ifdef _MSC_VER
# define CALL_CONVENTION __cdecl
# define CALL_IMPORT     __declspec(dllimport)
# else
# define CALL_CONVENTION
# define CALL_IMPORT
# endif

namespace {
    extern "C"
        typedef CALL_IMPORT int (CALL_CONVENTION *function_ptr)(int x, int y);
}



bool dll_lib(void)
{   bool ok = true;
    //
    // add_source
    std::string add_source =
        "int add(int x, int y)\n"
        "{   return x + y; }\n"
    ;
    //
    // dll_entry_source
    std::string dll_entry_source =
        "extern int add(int x, int y);"
# ifdef _MSC_VER
        "__declspec(dllexport) int _cdecl dll_entry(int x, int y)\n"
# else
        "int dll_entry(int x, int y)\n"
# endif
        "{   return add(x, y);}"
    ;
    //
    // temp_dir
    std::string temp_dir = std::filesystem::temp_directory_path().string();
    if( temp_dir.back() != DIR_SEP )
        temp_dir += DIR_SEP;
    //
    // ofs
    std::ofstream ofs;
    //
    // add_file
    std::string add_file = temp_dir + "add.c";
    ofs.open(add_file.c_str(), std::ofstream::out);
    ofs << add_source;
    ofs.close();
    //
    // dll_entry_file
    std::string dll_entry_file = temp_dir + "dll_entry.c";
    ofs.open(dll_entry_file.c_str(), std::ofstream::out);
    ofs << dll_entry_source;
    ofs.close();
    //
// BEGIN_OPTIONS
    // Example using options that are different from the default options
    std::map< std::string, std::string > options;
# ifdef _MSC_VER
    options["compile"] = "cl /EHs /EHc /c /TC /O2";
# elif CPPAD_LINK_FLAGS_HAS_M32
    options["compile"] = "gcc -c -fPIC -O2 -m32";
# else
    options["compile"] = "gcc -c -fPIC -O2";
# endif
// END_OPTIONS
    //
    // dll_file
    std::vector< std::string > csrc_files(2);
    csrc_files[0] = add_file;
    csrc_files[1] = dll_entry_file;
    std::string dll_file = temp_dir + "dll_entry" + DLL_EXT;
    CppAD::create_dll_lib(dll_file, csrc_files, options);
    //
    // dll_linker
    std::string err_msg;
    CppAD::link_dll_lib dll_linker(dll_file, err_msg);
    if( err_msg != "" )
    {   std::cerr << "dll_lib error: " << err_msg << "\n";
        return false;
    }
    //
    // dll_entry
    void* vptr = dll_linker("dll_entry", err_msg);
    if( err_msg != "" )
    {   std::cerr << "dll_lib error: " << err_msg << "\n";
        return false;
    }
    function_ptr dll_entry = reinterpret_cast<function_ptr>(vptr);
    //
    // z = dll_entry(x, y)
    int x = 1, y = 2;
    int z = dll_entry(x, y);
    //
    // ok
    ok &= z == (x + y);
    //
    return ok;
}