1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
// SPDX-FileContributor: 2003-25 Bradley M. Bell
// ----------------------------------------------------------------------------
/*
{xrst_begin dll_lib.cpp}
{xrst_spell
msvc
}
dll_lib: Example and Test
#########################
options
*******
The following subsection of this example sets
:ref:`create_dll_lib@options` that are different
from the default options:
{xrst_literal
// BEGIN_OPTIONS
// END_OPTIONS
}
Restrictions
************
This example is only built and run under the following conditions:
#. The :ref:`cmake-name` command determines that the C compiler is
gcc, clang, or msvc.
#. The :ref:`cmake-name` command determines it is OK to use
C++17 features.
#. The :ref:`cmake@cppad_link_flags` do not contain ``-m32`` .
Source
******
{xrst_literal
// BEGIN C++
// END C++
}
{xrst_end dll_lib.cpp}
*/
// BEGIN C++
# 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;
}
// END C++
|