Skip to content

Commit 9410dd2

Browse files
authored
projinfo as library function (#4646)
* Move projinfo to be able to call it in the library * calling projinfo with `--help` or `-?` produces a return code 0.
1 parent eabdc86 commit 9410dd2

File tree

10 files changed

+2528
-2113
lines changed

10 files changed

+2528
-2113
lines changed

scripts/ci/emscripten/build_wasm.sh

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,23 +248,66 @@ else
248248
fi
249249

250250
# --- 6.5 Create C Wrappers ---
251-
# Helper functions to extract some info from PROJ in C
251+
# Helper functions to extract some info from PROJ in C and C++
252252
log_step "6.5 Creating C Wrapper Functions"
253253

254-
WRAPPER_FILE="${TEMP_BUILD_DIR}/proj_wrappers.c"
254+
WRAPPER_FILE="${TEMP_BUILD_DIR}/proj_wrappers.cpp"
255255
WRAPPER_OBJ_FILE="${TEMP_BUILD_DIR}/proj_wrappers.o"
256256

257257
DDD=`date +"%Y-%m-%dT%H:%M:%S%z" -u`
258258
cat << EOF > ${WRAPPER_FILE}
259259
#include "proj.h"
260260
#include "math.h"
261261
262+
#include "projapps_lib.h"
263+
264+
#include <emscripten/bind.h>
265+
#include <emscripten/val.h>
266+
#include <vector>
267+
#include <string>
268+
269+
void trampoline(PJ_PROJINFO_LOG_LEVEL level, const char *msg, void *user_data) {
270+
if (!user_data) return;
271+
const emscripten::val* js_callback = reinterpret_cast<const emscripten::val*>(user_data);
272+
(*js_callback)(level, std::string(msg));
273+
}
274+
275+
int projinfo_wrapper(uintptr_t ctx_ptr, emscripten::val jsArgs, emscripten::val jsCallback) {
276+
std::vector<std::string> args = emscripten::vecFromJSArray<std::string>(jsArgs);
277+
std::vector<char*> argv;
278+
for (auto& s : args) {
279+
argv.push_back(&s[0]);
280+
}
281+
PJ_CONTEXT *ctx = reinterpret_cast<PJ_CONTEXT *>(ctx_ptr);
282+
return projinfo(ctx, args.size(), argv.data(), &trampoline, &jsCallback);
283+
}
284+
285+
EMSCRIPTEN_BINDINGS(proj_module) {
286+
emscripten::value_object<PJ_INFO>("PJ_INFO")
287+
.field("major", &PJ_INFO::major)
288+
.field("minor", &PJ_INFO::minor)
289+
.field("patch", &PJ_INFO::patch)
290+
.field("release", std::function<std::string(const PJ_INFO&)>([](const PJ_INFO& i) {
291+
return std::string(i.release); }),
292+
std::function<void(PJ_INFO&, std::string)>([](PJ_INFO& i, std::string v) {}))
293+
.field("version", std::function<std::string(const PJ_INFO&)>([](const PJ_INFO& i) {
294+
return std::string(i.version); }),
295+
std::function<void(PJ_INFO&, std::string)>([](PJ_INFO& i, std::string v) {}));
296+
emscripten::function("proj_info_ems", &proj_info);
297+
298+
emscripten::enum_<PJ_PROJINFO_LOG_LEVEL>("PJ_PROJINFO_LOG_LEVEL")
299+
.value("INFO", PJ_PROJINFO_LOG_LEVEL_INFO)
300+
.value("WARN", PJ_PROJINFO_LOG_LEVEL_WARN)
301+
.value("ERR", PJ_PROJINFO_LOG_LEVEL_ERR);
302+
303+
emscripten::function("projinfo_ems", &projinfo_wrapper, emscripten::allow_raw_pointers());
304+
}
305+
306+
extern "C" {
307+
262308
const char* get_compilation_date() {
263309
return "$DDD" ;
264310
}
265-
266-
int get_proj_info_sizeof() {
267-
return sizeof(PJ_INFO);
268311
}
269312
EOF
270313

@@ -290,6 +333,7 @@ FINAL_LIBS="${INSTALL_DIR}/lib/libproj.a \
290333
emcc -v ${FINAL_LIBS} \
291334
-o ${INSTALL_DIR}/projModule.js \
292335
-O3 \
336+
-lembind \
293337
-s STACK_OVERFLOW_CHECK=1 \
294338
-s STACK_SIZE=5MB \
295339
-s NO_DISABLE_EXCEPTION_CATCHING \
@@ -303,7 +347,6 @@ emcc -v ${FINAL_LIBS} \
303347
-s ALLOW_MEMORY_GROWTH=1 \
304348
-s EXPORTED_RUNTIME_METHODS="[ccall, cwrap, FS, HEAPF64, stringToNewUTF8, UTF8ToString, getValue]" \
305349
-s EXPORTED_FUNCTIONS="[
306-
_get_proj_info_sizeof,
307350
_get_compilation_date,
308351
_proj_info,
309352
_proj_context_errno_string,

scripts/reference_exported_symbols.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,7 @@ proj_grid_cache_set_ttl
10831083
proj_grid_get_info_from_database
10841084
proj_grid_info
10851085
proj_identify
1086+
projinfo
10861087
proj_info
10871088
proj_init_info
10881089
proj_insert_object_session_create

src/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
add_compile_options("$<$<COMPILE_LANGUAGE:C>:${PROJ_C_WARN_FLAGS}>")
33
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:${PROJ_CXX_WARN_FLAGS}>")
44

5+
# 0: include the lib files for the apps.
6+
include(apps/lib_projapps.cmake)
7+
58
# First configure proj library
69
include(lib_proj.cmake)
710
add_subdirectory(apps)

src/apps/lib_projapps.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
set(SRC_PROJAPPS_LIBS
2+
apps/projinfo_lib.cpp
3+
)
4+
set(HEADERS_PROJAPPS_LIBS apps/projapps_lib.h)

src/apps/projapps_lib.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/******************************************************************************
2+
*
3+
* Project: PROJ
4+
* Purpose: projinfo C API
5+
* Author: Javier Jimenez Shaw
6+
*
7+
******************************************************************************
8+
* Copyright (c) 2025 Javier Jimenez Shaw
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a
11+
* copy of this software and associated documentation files (the "Software"),
12+
* to deal in the Software without restriction, including without limitation
13+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
14+
* and/or sell copies of the Software, and to permit persons to whom the
15+
* Software is furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included
18+
* in all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26+
* DEALINGS IN THE SOFTWARE.
27+
****************************************************************************/
28+
29+
#if !defined(PROJAPPS_LIB_H)
30+
#define PROJAPPS_LIB_H
31+
32+
#include "proj.h"
33+
34+
#ifdef __cplusplus
35+
extern "C" {
36+
#endif
37+
38+
/*
39+
* Level for the output given by projinfo in its callback.
40+
*/
41+
typedef enum {
42+
PJ_PROJINFO_LOG_LEVEL_INFO = 1,
43+
PJ_PROJINFO_LOG_LEVEL_WARN = 2,
44+
PJ_PROJINFO_LOG_LEVEL_ERR = 3,
45+
} PJ_PROJINFO_LOG_LEVEL;
46+
47+
typedef void (*projinfo_cb_t)(PJ_PROJINFO_LOG_LEVEL level, const char *msg,
48+
void *user_data);
49+
50+
/*
51+
* Internal C implementation of projinfo CLI application.
52+
* See https://proj.org/apps/projinfo.html for more documentation.
53+
* @param ctx context. It can be nullptr.
54+
* @param argc number for parameters in argv.
55+
* @param argv list of char* with the command parameters of projinfo.
56+
* It does not contain the program name as first parameter.
57+
* @param cb callback that to get the output of projinfo.
58+
* It can be very fragmented, no necesarily by lines.
59+
* @param user_data pointer for data passed to the callback.
60+
*/
61+
int PROJ_DLL projinfo(PJ_CONTEXT *ctx, int argc, char **argv, projinfo_cb_t cb,
62+
void *user_data);
63+
64+
#ifdef __cplusplus
65+
}
66+
#endif
67+
68+
#endif

0 commit comments

Comments
 (0)