第5讲:建立自己的C函数库,js调用自己写的C/C++函数,并包含依赖C/C++第三方静态库。

06-27 1015阅读

在javascript中,Array有很多内置的功能,比如Array.map,Array.filter,Array.find等等,能用内置的功能就用内置的功能,最好不要自己实现一套,因为底层调用的可能压根就不是js语言本身,底层的实现可能由C/C++实现的。如果我们要做的一些功能,需要高性能密集计算,但是JavaScript内置函数无法满足我们要求的时候,这时候我们就要自己用C/C++编写一个程序,然后封装成wasm文件给JavaScript调用了,此时wasm还包含了.a文件这样的第三方库。

我们这里有个需求,就是在地球上有两艘船,船A和船B在某个经纬度位置触发,以某个航向、速度行驶,求它们间最小距离是多少,达到最小距离的时候,经过时间是多少秒?

首先这个功能用C/C++来编写,并且还要用到开源第三方库。

下图的红圈注释里面有几个参数,分别表示经度、纬度、速度、航向,当然getCPA最后一个参数6.5表示6.5分钟的时间长度。表示计算6.5分钟以内,两船最小距离是多少,并且到达最小距离时,经过时间是多少。

第5讲:建立自己的C函数库,js调用自己写的C/C++函数,并包含依赖C/C++第三方静态库。

打开Visual Studio 2022,新建一个cmake工程,项目名称为GeoCompute。这仅仅是一个测试项目,如果测试通过,没有问题了,就把该代码交给emcc或者em++去编译。

CMakeLists.txt文件内容如下:

在这里,我采用vcpkg来安装GeographicLib库

可以执行如下命令安装。

vcpkg install GeographicLib:x64-windows
# CMakeList.txt: GeoCompute 的 CMake 项目,在此处包括源代码并定义
# 项目特定的逻辑。
#
cmake_minimum_required (VERSION 3.8)
set(VCPKG_ROOT "D:/CppPkg/WinVcpkg/vcpkg" CACHE PATH "")
set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
# Enable Hot Reload for MSVC compilers if supported.
if (POLICY CMP0141)
  cmake_policy(SET CMP0141 NEW)
  set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$,$>")
endif()
project ("GeoCompute")
# 将源代码添加到此项目的可执行文件。
add_executable (GeoCompute "GeoCompute.cpp"  )
find_package (GeographicLib CONFIG REQUIRED)
target_link_libraries (GeoCompute PRIVATE ${GeographicLib_LIBRARIES})
if (CMAKE_VERSION VERSION_GREATER 3.12)
  set_property(TARGET GeoCompute PROPERTY CXX_STANDARD 20)
endif()
# TODO: 如有需要,请添加测试并安装目标。

然后编写一个GeoCompute.cpp文件

#include 
#include 
#include 
#include 
#include 
const double EARTH_RADIUS = 6377830.0;  // 地球的平均半径,单位为千米
const double M_PI = 3.14159265359;
struct LatLon {
    double first;
    double second;
};
double deg2rad(double deg) {
    return deg * M_PI / 180.0;
}
double haversine_distance(double lat1, double lon1, double lat2, double lon2) {
    double dlat = deg2rad(lat2 - lat1);
    double dlon = deg2rad(lon2 - lon1);
    double a = std::sin(dlat / 2) * std::sin(dlat / 2) +
        std::cos(deg2rad(lat1)) * std::cos(deg2rad(lat2)) *
        std::sin(dlon / 2) * std::sin(dlon / 2);
    double c = 2 * std::atan2(std::sqrt(a), std::sqrt(1 - a));
    return EARTH_RADIUS * c;
}
LatLon new_position_with_geolib(double lat, double lon, double speed, double cog, double T) {
    const GeographicLib::Geodesic& geod = GeographicLib::Geodesic::WGS84();
    double s12 = speed * T;
    double lat2, lon2;
    // Direct method gives the destination point given start point, initial azimuth, and distance
    geod.Direct(lat, lon, cog, s12, lat2, lon2);
    return { lat2, lon2 };
}
double new_distance(double T, double latA, double lonA, double speedA, double cogA, double latB, double lonB, double speedB, double cogB) {
    auto resA = new_position_with_geolib(latA, lonA, speedA, cogA, T);
    auto resB = new_position_with_geolib(latB, lonB, speedB, cogB, T);
    return haversine_distance(resA.first, resA.second, resB.first, resB.second);
}
LatLon getCPA(double latA, double lonA, double speedA, double cogA, double latB, double lonB, double speedB, double cogB, double tcpa) {
    double RES_TCPA = INFINITY;
    double RES_DCPA = INFINITY;
    double prev_dist = INFINITY;
    double cur_dist = INFINITY;
    std::vector status;
    int t_lim = tcpa * 60;
    int step = 1;
    if (t_lim > 600) {
        step = int(double(t_lim) / 300.0);
    }
    for (int t = 0;t > 3]; // 读取double指针的第0个元素
    const res_dcpa = instance.HEAPF64[(resultPtr >> 3) + 1]; // 读取地址偏移量+1
    console.log('TCPA:', res_tcpa);
    console.log('DCPA:', res_dcpa);
    console.log('Continuing after runtime initialization.');
    // 继续下面的逻辑...
  } catch (error) {
    console.error('Error:', error);
  }
}
main();

index.html的内容:



  
  
  Blank Window


  


package.json的内容:

{
  "name": "nodedevtest",
  "version": "1.0.0",
  "description": "A minimal Electron application",
  "main": "main.js",
  "scripts": {
    "start": "node main.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^1.6.8",
    "electron": "^30.0.1",
    "pixi.js": "^8.1.0",
    "request": "^2.88.2"
  }
}

得出的结果:

第5讲:建立自己的C函数库,js调用自己写的C/C++函数,并包含依赖C/C++第三方静态库。

得出的结果是154和1519.5687501879786

表示经过154秒以后,两船达到最小距离,并且最小距离为1519米多。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]