diff --git a/CMakeLists.txt b/CMakeLists.txt index cd427a91191a55ca71365b5db2a82a23718074a4..a1a89ed089816e44423fdc2e8e0c86eaa91c6afc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,7 @@ adios_option(ZeroMQ "Enable support for ZeroMQ" AUTO) adios_option(HDF5 "Enable support for the HDF5 engine" AUTO) adios_option(ADIOS1 "Enable support for the ADIOS 1.x engine" AUTO) adios_option(Python "Enable support for Python bindings" AUTO) +adios_option(C "Enable support for C bindings" AUTO) adios_option(SysVShMem "Enable support for SysV Shared Memory IPC on *NIX" AUTO) include(${ADIOS2_SOURCE_DIR}/cmake/DetectOptions.cmake) @@ -106,7 +107,7 @@ if(ADIOS2_HAVE_MPI) add_definitions(-DOMPI_SKIP_MPICXX) endif() -GenerateADIOSHeaderConfig(MPI ZFP BZip2 ADIOS1 HDF5 DataMan Python SysVShMem) +GenerateADIOSHeaderConfig(MPI ZFP BZip2 ADIOS1 HDF5 DataMan Python C SysVShMem) install(FILES ${ADIOS2_BINARY_DIR}/source/adios2/ADIOSConfig.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/adios2 ) @@ -181,7 +182,7 @@ message(" Library Type: ${msg_lib_type}") message(" Build Type: ${CMAKE_BUILD_TYPE}") message(" Testing: ${BUILD_TESTING}") message(" Build Options:") -foreach(opt BZip2 ZFP MPI DataMan ZeroMQ HDF5 ADIOS1 Python SysVShMem) +foreach(opt BZip2 ZFP MPI DataMan ZeroMQ HDF5 ADIOS1 Python C SysVShMem) message_pad(" ${opt}" 15 label) if(${ADIOS2_HAVE_${opt}}) message("${label}: ON") diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt index c21b8b329a9fe124899f3629e3a76f423ef66338..b169d708860f8c20698b3980e9160624bb40f286 100644 --- a/bindings/CMakeLists.txt +++ b/bindings/CMakeLists.txt @@ -1,3 +1,9 @@ + + if(ADIOS2_HAVE_Python) add_subdirectory(python) endif() + +if(ADIOS2_HAVE_C) + add_subdirectory(c) +endif() diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..515c0b74cd7461da3f33257e72d7d74ad69c2752 --- /dev/null +++ b/bindings/c/CMakeLists.txt @@ -0,0 +1,37 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +set(adios2_c_targets) + +add_library(adios2_c adios2_c.cpp) +target_link_libraries(adios2_c PRIVATE adios2) + +if(ADIOS2_HAVE_MPI) + find_package(MPI COMPONENTS C REQUIRED) + target_compile_definitions(adios2_c PUBLIC ADIOS2_HAVE_MPI_C) + target_include_directories(adios2_c PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${MPI_C_INCLUDE_PATH}) + target_link_libraries(adios2_c PRIVATE ${MPI_C_LIBRARIES}) +else() + target_include_directories(adios2_c PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +list(APPEND adios2_c_targets adios2_c) + +install( + TARGETS ${adios2_c_targets} EXPORT adios2 + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +install( + FILES adios2_c.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + +install( + FILES adios2/adios2_c_enums.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/adios2 +) \ No newline at end of file diff --git a/bindings/c/adios2_c_enums.h b/bindings/c/adios2/adios2_c_enums.h similarity index 100% rename from bindings/c/adios2_c_enums.h rename to bindings/c/adios2/adios2_c_enums.h diff --git a/bindings/c/adios2_c.cpp b/bindings/c/adios2_c.cpp index a94eb85023dc8281aa9dd821206e86eead4dd874..432a3dac4d3ea8ac8d2de7efd70041b620f989cd 100644 --- a/bindings/c/adios2_c.cpp +++ b/bindings/c/adios2_c.cpp @@ -15,6 +15,10 @@ #include <adios2.h> +#ifndef ADIOS2_HAVE_MPI_C +#define MPI_COMM_SELF 2 +#endif + adios2_ADIOS *adios2_init_config(const char *config_file, MPI_Comm mpi_comm, const adios2_debug_mode debug_mode) { @@ -159,11 +163,9 @@ adios2_define_variable(adios2_IO *io, const char *name, const adios2_type type, break; case (adios2_type_double_complex): - - // variable = dynamic_cast<adios2::Variable<std::complex<double>> - // *>( - // &ioCpp.DefineVariable<std::complex<double>>( - // name, shapeV, startV, countV, constantSizeBool)); + variable = dynamic_cast<adios2::Variable<std::complex<double>> *>( + &ioCpp.DefineVariable<std::complex<double>>( + name, shapeV, startV, countV, constantSizeBool)); break; case (adios2_type_int8_t): @@ -249,7 +251,15 @@ struct adios2_Engine }; adios2_Engine *adios2_open(adios2_IO *io, const char *name, - const adios2_open_mode open_mode, MPI_Comm mpi_comm) + const adios2_open_mode open_mode) +{ + auto &ioCpp = *reinterpret_cast<adios2::IO *>(io); + return adios2_open_new_comm(io, name, open_mode, ioCpp.m_MPIComm); +} + +adios2_Engine *adios2_open_new_comm(adios2_IO *io, const char *name, + const adios2_open_mode open_mode, + MPI_Comm mpi_comm) { auto &ioCpp = *reinterpret_cast<adios2::IO *>(io); adios2_Engine *engine = new adios2_Engine; diff --git a/bindings/c/adios2_c.h b/bindings/c/adios2_c.h index 5ddb07b41c729d7fd02da481c733f8691e20d8b2..c0d94164ec65239c87ad8ec5f3668e5e2944bd4f 100644 --- a/bindings/c/adios2_c.h +++ b/bindings/c/adios2_c.h @@ -11,10 +11,9 @@ #ifndef ADIOS2_BINDINGS_C_ADIOS2_C_H_ #define ADIOS2_BINDINGS_C_ADIOS2_C_H_ -#include <mpi.h> //TODO: resolve mpi or mpidummy #include <stddef.h> //size_t -#include "adios2_c_enums.h" +#include "adios2/adios2_c_enums.h" typedef void adios2_ADIOS; typedef void adios2_IO; @@ -25,6 +24,12 @@ typedef struct adios2_Engine adios2_Engine; extern "C" { #endif +#ifdef ADIOS2_HAVE_MPI_C +#include <mpi.h> +#else +typedef int MPI_Comm; +#endif + /** * Create an ADIOS struct pointer handler using a runtime config file in MPI * application. @@ -127,15 +132,52 @@ void adios2_set_transport_param(adios2_IO *io, const unsigned int transport_index, const char *key, const char *value); +/** + * Create an adios2_Engine, from adios2_IO, that executes all IO operations. + * Resuse MPI_Comm passed to adios2_ADIOS that created adios2_IO io + * @param io input that creates the adios2_Engine + * @param name engine name + * @param open_mode read, write, append use adios2_open_mode enum + * @return engine handler + */ adios2_Engine *adios2_open(adios2_IO *io, const char *name, - const adios2_open_mode open_mode, MPI_Comm mpi_comm); + const adios2_open_mode open_mode); +/** + * Create an adios2_Engine, from adios2_IO, that executes all IO operations. + * Allows passing a new communicator. + * @param io input that creates the adios2_Engine + * @param name engine name + * @param open_mode read, write, append use adios2_open_mode enum + * @param mpi_comm allows passing a new MPI communicator + * @return engine handler + */ +adios2_Engine *adios2_open_new_comm(adios2_IO *io, const char *name, + const adios2_open_mode open_mode, + MPI_Comm mpi_comm); + +/** + * Write a variable using a adios2_Variable handler + * @param engine handler for engine executing the write + * @param variable handler for variable from adios2_define_variable + * @param values application data to be written for this variable + */ void adios2_write(adios2_Engine *engine, adios2_Variable *variable, const void *values); +/** + * Write a variable using a variable name created from adios2_define_variable + * @param engine handler for engine executing the write + * @param variable_name unique variable name, within io that create the engine. + * @param values application data to be written for this variable + */ void adios2_write_by_name(adios2_Engine *engine, const char *variable_name, const void *values); +/** + * Advance time step for writes + * @param engine handler executing IO tasks + */ void adios2_advance(adios2_Engine *engine); /** @@ -145,12 +187,19 @@ void adios2_advance(adios2_Engine *engine); */ void adios2_close(adios2_Engine *engine); +/** + * Close a particular transport from the index returned by adios2_add_transport + * @param engine handler containing all transports to + * be closed. NOTE: engine NEVER becomes NULL due to this function. + * @param transport_index handler from adios2_add_transport + */ void adios2_close_by_index(adios2_Engine *engine, const unsigned int transport_index); /** - * Deallocate adios pointer - * @param adios input to be deallocated, all destrcutors called + * Final point for adios2_ADIOS handler. + * Deallocate adios pointer. Required to avoid memory leaks. + * @param adios input to be deallocated */ void adios2_finalize(adios2_ADIOS *adios); diff --git a/cmake/ADIOS2ConfigCommon.cmake.in b/cmake/ADIOS2ConfigCommon.cmake.in index 945a97a9810c9c3c70364bf7d0ba8e218f4881cf..c3b62379d3fc1109414c91e860d3b3f900f08d73 100644 --- a/cmake/ADIOS2ConfigCommon.cmake.in +++ b/cmake/ADIOS2ConfigCommon.cmake.in @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.5) include(CMakeFindDependencyMacro) +set(ADIOS2_HAVE_C @ADIOS2_HAVE_C@) +if(ADIOS2_HAVE_C) + find_dependency(C) +endif() + set(ADIOS2_HAVE_MPI @ADIOS2_HAVE_MPI@) if(ADIOS2_HAVE_MPI) find_dependency(MPI) diff --git a/cmake/DetectOptions.cmake b/cmake/DetectOptions.cmake index 5022c676d3c31fe1dbaa82907f0ec9b72417a614..bc9d2aba3d626565c2858d842089010d96376dfb 100644 --- a/cmake/DetectOptions.cmake +++ b/cmake/DetectOptions.cmake @@ -43,6 +43,11 @@ elseif(ADIOS2_USE_MPI) set(ADIOS2_HAVE_MPI TRUE) endif() +# C +if(ADIOS2_USE_C) + set(ADIOS2_HAVE_C TRUE) +endif() + # DataMan if(ADIOS2_USE_DataMan STREQUAL AUTO) if(SHARED_LIBS_SUPPORTED AND NOT MSVC) diff --git a/examples/hello/bpWriter/CMakeLists.txt b/examples/hello/bpWriter/CMakeLists.txt index c252a25e6409a13177f7172b21962f93d33e0677..ba4172948b1a8ebf3ba28c831d1fe0fecc0ae275 100644 --- a/examples/hello/bpWriter/CMakeLists.txt +++ b/examples/hello/bpWriter/CMakeLists.txt @@ -10,9 +10,23 @@ if(ADIOS2_HAVE_MPI) target_include_directories(hello_bpWriter PRIVATE ${MPI_C_INCLUDE_PATH}) target_link_libraries(hello_bpWriter ${MPI_C_LIBRARIES}) + if(ADIOS2_HAVE_C) + add_executable(hello_bpWriter_c helloBPWriter.c) + target_include_directories(hello_bpWriter_c PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(hello_bpWriter_c ${MPI_C_LIBRARIES}) + endif() + else() add_executable(hello_bpWriter helloBPWriter_nompi.cpp) + if(ADIOS2_HAVE_C) + add_executable(hello_bpWriter_c helloBPWriter_nompi.c) + endif() + endif() target_link_libraries(hello_bpWriter adios2) + +if(ADIOS2_HAVE_C) + target_link_libraries(hello_bpWriter_c adios2_c adios2) +endif() \ No newline at end of file diff --git a/examples/hello/bpWriter/helloBPWriter.c b/examples/hello/bpWriter/helloBPWriter.c index 1c805a09f69a1c6b8147d0c70b2f786767cc7efe..6bc7f45d3b25ce48244d6e24006b44d330f3246e 100644 --- a/examples/hello/bpWriter/helloBPWriter.c +++ b/examples/hello/bpWriter/helloBPWriter.c @@ -8,7 +8,7 @@ * Author: William F Godoy godoywf@ornl.gov */ #include <mpi.h> -#include <stdlib.h> +#include <stdlib.h> // malloc, free #include <adios2_c.h> @@ -19,7 +19,7 @@ int main(int argc, char *argv[]) MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); - // application input + // application input, data in heap const size_t Nx = 10; float *myFloats; myFloats = malloc(sizeof(float) * Nx); @@ -47,7 +47,7 @@ int main(int argc, char *argv[]) adios2_define_variable(ioH, "bpFloats", adios2_type_float, 1, shape, start, count, adios2_constant_dims_true); adios2_Engine *engineH = - adios2_open(ioH, "myVector.bp", adios2_open_mode_write, MPI_COMM_WORLD); + adios2_open(ioH, "myVector_c.bp", adios2_open_mode_write); adios2_write(engineH, variableH, myFloats); adios2_close(engineH); diff --git a/examples/hello/bpWriter/helloBPWriter_nompi.c b/examples/hello/bpWriter/helloBPWriter_nompi.c new file mode 100644 index 0000000000000000000000000000000000000000..c86e78be613f4e9c2a59b7fbb69cb48fa442f896 --- /dev/null +++ b/examples/hello/bpWriter/helloBPWriter_nompi.c @@ -0,0 +1,48 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * helloBPWriter_nompi.c : C bindings version of C++11 helloBPWriter_nompi.cpp + * + * Created on: Aug 8, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <stdlib.h> //malloc, free + +#include <adios2_c.h> + +int main(int argc, char *argv[]) +{ + // application input, data in heap + const size_t Nx = 10; + float *myFloats; + myFloats = malloc(sizeof(float) * Nx); + + unsigned int i; + for (i = 0; i < Nx; ++i) + { + myFloats[i] = i; + } + + adios2_ADIOS *adiosH = adios2_init_nompi(adios2_debug_mode_on); + adios2_IO *ioH = adios2_declare_io(adiosH, "BPFile_N2N"); + + // count dims are allocated in stack + size_t count[1]; + count[0] = Nx; + + adios2_Variable *variableH = + adios2_define_variable(ioH, "bpFloats", adios2_type_float, 1, NULL, + NULL, count, adios2_constant_dims_true); + adios2_Engine *engineH = + adios2_open(ioH, "myVector_c.bp", adios2_open_mode_write); + + adios2_write(engineH, variableH, myFloats); + adios2_close(engineH); + adios2_finalize(adiosH); + + free(myFloats); + + return 0; +} diff --git a/source/adios2/ADIOSConfig.h.in b/source/adios2/ADIOSConfig.h.in index 2ed35a170040bebcd83e0466c29a9127e9e8fc97..01c3d877ebfe723c6b88c4c041361482b00e1e14 100644 --- a/source/adios2/ADIOSConfig.h.in +++ b/source/adios2/ADIOSConfig.h.in @@ -42,10 +42,14 @@ /* CMake Option: ADIOS_USE_DataMan=ON */ #cmakedefine ADIOS2_HAVE_DATAMAN +/* CMake Option: ADIOS_USE_SysVShMem=ON */ +#cmakedefine ADIOS2_HAVE_SYSVSHMEM + +/* Language Bindings: */ /* CMake Option: ADIOS_USE_Python=ON */ #cmakedefine ADIOS2_HAVE_PYTHON -/* CMake Option: ADIOS_USE_SysVShMem=ON */ -#cmakedefine ADIOS2_HAVE_SYSVSHMEM +/* CMake Option: ADIOS_USE_C=ON */ +#cmakedefine ADIOS2_HAVE_C #endif /* ADIOSCONFIG_H_ */