CGAL WASM Скомпилированная библиотека, доступ к памяти вне границC++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 CGAL WASM Скомпилированная библиотека, доступ к памяти вне границ

Сообщение Anonymous »

В настоящее время я пытаюсь сделать библиотеку, которая запускает программную программу CGAL WASM. < /p>
main.cpp выглядит так: < /p>
#ifdef EMSCRIPTEN
// #define CGAL_ALWAYS_ROUND_TO_NEAREST
#define CGAL_NO_ASSERTIONS
#define CGAL_NO_PRECONDITIONS
#define CGAL_NO_POSTCONDITIONS
#define CGAL_NO_WARNINGS
#include
#include
#endif

#include
#include
#include
#include
#include
#include
// #include
#include
#include
#include
#include
#include

// Override make_certain to fix errors. Not sure why Uncertain doesn't work properly in Wasm environment.
template
bool CGAL::Uncertain::make_certain() const
{
return _i;
}

template
CGAL::Sign CGAL::Uncertain::make_certain() const
{
return _i;
}

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point;
typedef CGAL::Polygon_2 Polygon_2;
typedef CGAL::Polygon_with_holes_2 Polygon_with_holes;
typedef CGAL::Straight_skeleton_2 Ss;
typedef boost::shared_ptr SsPtr;
typedef CGAL::Exact_predicates_inexact_constructions_kernel CGAL_KERNEL;

// Decodes rings from data and generates a weighted skeleton from them.
// Data contains a list of rings, each ring is represented by a number of points (uint32_t), followed by the points
// themselves (each point is represented by 2 floats: x, y).
// The last value is 0.
// Additionally, a vector of weights is provided, where each weight corresponds to a vertex.
SsPtr generate_weighted_skeleton(void *data, const std::vector &weights)
{
uint32_t *data_uint32 = (uint32_t *)data;
uint32_t points = data_uint32[0];

assert(points != 0);
assert(points > 2);

++data_uint32;

Polygon_2 outer;
Polygon_2 hole;
Polygon_with_holes poly;
bool outer_set = false;

while (points != 0)
{
Polygon_2 *target = outer_set ? &hole : &outer;

for (long i = 0; i < points; i++)
{
float x = *((float *)data_uint32 + i * 2);
float y = *((float *)data_uint32 + i * 2 + 1);

target->push_back(Point(x, y));
}

data_uint32 += points * 2;

points = data_uint32[0];

++data_uint32;

if (!outer_set)
{
assert(outer.is_counterclockwise_oriented());
poly = Polygon_with_holes(outer);
outer_set = true;
}
else
{
assert(hole.is_clockwise_oriented());
poly.add_hole(hole);
hole.clear();
}
}

return CGAL::create_interior_weighted_straight_skeleton_2(poly, weights, CGAL_KERNEL());
}

// Serializes a skeleton into a format that can be sent to the JS side.
// The first part of the data describes the vertices:
// The first value (uint32_t) specifies the number of vertices.
// After that, each vertex is represented by 3 floats: x, y, time.
// Then, the second part describes the faces:
// Each face is represented by a uint32_t specifying the number of vertices in the face, followed by the indices
// of its vertices (also uint32_t).
// The last value is 0.
void *serialize_skeleton(SsPtr iss)
{
if (iss == nullptr)
{
return nullptr;
}

std::unordered_map vertex_map;
std::vector vertices;

for (auto vertex = iss->vertices_begin(); vertex != iss->vertices_end(); ++vertex)
{
CGAL::Point_2 point = vertex->point();

vertices.emplace_back(point.x(), point.y(), vertex->time());
vertex_map[vertex] = vertices.size() - 1;
}

std::vector faces;
int total_vertices = 0;

for (auto face = iss->faces_begin(); face != iss->faces_end(); ++face)
{
std::vector face_polygon;

for (auto h = face->halfedge();;)
{
auto vertex_index = (uint32_t)vertex_map[h->vertex()];
face_polygon.push_back(vertex_index);
++total_vertices;

h = h->next();

if (h == face->halfedge())
{
break;
}
}

faces.emplace_back(face_polygon);
}

int total_size = 1 + vertices.size() * 3 + faces.size() + total_vertices + 1;
uint32_t *data = (uint32_t *)malloc(total_size * sizeof(uint32_t));
float *data_float = (float *)data;
int i = 0;

data[i++] = vertices.size();

for (auto vertex : vertices)
{
data_float[i++] = std::get(vertex);
data_float[i++] = std::get(vertex);
data_float[i++] = std::get(vertex);
}

for (auto face : faces)
{
data[i++] = face.size();

for (auto vertex_index : face)
{
data[i++] = vertex_index;
}
}

data[i++] = 0;

return data;
}

extern "C"
{
EMSCRIPTEN_KEEPALIVE
void *create_weighted_straight_skeleton(void *data, const std::vector &weights)
{

// // Polygon-Daten
// uint32_t polygon_data[] = {

// 4, // Anzahl der Punkte im äußeren Polygon
// 0, 0, // Punkt 1
// 10, 8, // Punkt 3
// 10, 10, // Punkt 3
// 0, 10, // Punkt 2

// // 4, // Anzahl der Punkte im inneren Loch
// // 2, 2, // Punkt 1
// // 2, 8, // Punkt 2
// // 8, 8, // Punkt 3
// // 8, 2, // Punkt 4
// 0 // Ende der Daten
// };

// // Gewichte
// std::vector testweights = {
// {}, // Gewichte für das äußere Polygon
// // {0.5, 0.5, 0.5, 0.5} // Gewichte für das innere Loch
// };

SsPtr skeleton = generate_weighted_skeleton(data, weights);

return serialize_skeleton(skeleton);
}
}

< /code>
Wapper in ts выглядит следующим образом: < /p>

//@ts-ignore
import Module from '../core/build/main.js';

interface WasmModule {
HEAPU8: Uint8Array;
HEAPU32: Uint32Array;
HEAPF32: Float32Array;
_malloc(size: number): number;
_free(ptr: number): void;
_create_weighted_straight_skeleton(ptr: number, weightsPtr: number): number;
}

/**
* Each skeleton vertex is represented by x, y and time. Time can be used to calculate z coordinate.
*/
export type Vertex = [number, number, number];

/**
* Each polygon is represented by an array of vertex indices.
*/
export type Polygon = number[];

/**
* Straight skeleton calculation result.
*/
export interface Skeleton {
vertices: Vertex[];
polygons: Polygon[];
}

export class SkeletonBuilder {
private static module: WasmModule = null;

/**
* Initializes the WebAssembly module. Must be called before any other method.
*/
public static async init(): Promise {
return Module().then((library: WasmModule) => {
this.module = library;
});
}

/**
* Builds a skeleton from a GeoJSON polygon.
* The polygon must have at least one ring. The first ring is always the outer ring, and the rest are inner rings.
* Outer rings must be counter-clockwise oriented and inner rings must be clockwise oriented.
* All rings must be weakly simple.
* Each ring must have a duplicate of the first vertex at the end.
* @param polygon The GeoJSON polygon.
* @param weights The weights for each vertex.
*/
public static buildFromGeoJSONPolygon(polygon: GeoJSON.Polygon, weights: number[][]): Skeleton {
this.checkModule();
return this.buildFromPolygon(polygon.coordinates, weights);
}

/**
* Builds a skeleton from a polygon represented as an array of rings.
* The polygon must have at least one ring. The first ring is always the outer ring, and the rest are inner rings.
* Outer rings must be counter-clockwise oriented and inner rings must be clockwise oriented.
* All rings must be weakly simple.
* Each ring must have a duplicate of the first vertex at the end.
* @param coordinates The polygon represented as an array of rings.
* @param weights The weights for each vertex.
*/
public static buildFromPolygon(coordinates: number[][][], weights: number[][]): Skeleton {
this.checkModule();

const inputBuffer = this.serializeInput(coordinates);
const inputPtr = this.module._malloc(inputBuffer.byteLength);
this.module.HEAPU8.set(new Uint8Array(inputBuffer), inputPtr);

const weightsBuffer = this.serializeWeights(weights);
console.log("DEBUG WEIGHTSBUFFER", new Float32Array(weightsBuffer))
const weightsPtr = this.module._malloc(weightsBuffer.byteLength);
this.module.HEAPU8.set(new Uint8Array(weightsBuffer), weightsPtr);

const ptr = this.module._create_weighted_straight_skeleton(inputPtr, weightsPtr);
if (ptr === 0) {
return null;
}

let offset = ptr / 4;
const arrayU32 = this.module.HEAPU32;
const arrayF32 = this.module.HEAPF32;

const vertices: Vertex[] = [];
const polygons: number[][] = [];

const vertexCount = arrayU32[offset++];

for (let i = 0; i < vertexCount; i++) {
const x = arrayF32[offset++];
const y = arrayF32[offset++];
const time = arrayF32[offset++];

vertices.push([x, y, time]);
}

let polygonVertexCount = arrayU32[offset++];

while (polygonVertexCount > 0) {
const polygon = [];

for (let i = 0; i < polygonVertexCount; i++) {
polygon.push(arrayU32[offset++]);
}

polygons.push(polygon);
polygonVertexCount = arrayU32[offset++];
}

// this.module._free(ptr);
// this.module._free(inputPtr);
// this.module._free(weightsPtr);

return { vertices, polygons };
}

private static checkModule(): void {
if (this.module === null) {
throw new Error('The WebAssembly module has not been initialized, call SkeletonBuilder.init() first.');
}
}

private static serializeInput(input: number[][][]): ArrayBuffer {
let size: number = 1;

for (const ring of input) {
size += 1 + (ring.length - 1) * 2;
}

const uint32Array = new Uint32Array(size);
const float32Array = new Float32Array(uint32Array.buffer);
let offset = 0;

for (const ring of input) {
uint32Array[offset++] = ring.length - 1;

for (let i = 0; i < ring.length - 1; i++) {
float32Array[offset++] = ring[0];
float32Array[offset++] = ring[1];
}
}

uint32Array[offset++] = 0;
return float32Array.buffer;
}

private static serializeWeights(weights: number[][]): ArrayBuffer {
let size: number = 0;

for (const ringWeights of weights) {
size += ringWeights.length;
}

const float32Array = new Float32Array(size);
let offset = 0;

for (const ringWeights of weights) {
for (const weight of ringWeights) {
float32Array[offset++] = weight;
}
}

return float32Array.buffer;
}
}

< /code>
Проблема, по -видимому, заключается в функции serializeweights. Каким -то образом я испорчу типы или указатели, или что -то, что я не вижу. Если я не использую веса, которые были перенесены в CPP, а вместо этого использую пустой {} здесь, в последней строке CPP (Generate_weighted_skeleton (data, испытательный вес); тогда код работает и не возвращает проблемы.
Я предполагаю, что я устанавливаю неправильный буфер здесь: < /p>
const weightsBuffer = this.serializeWeights(weights);
console.log("DEBUG WEIGHTSBUFFER", new Float32Array(weightsBuffer))
const weightsPtr = this.module._malloc(weightsBuffer.byteLength);
this.module.HEAPU8.set(new Uint8Array(weightsBuffer), weightsPtr);
< /code>
Но я не могу понять, в чем проблема. Скомпилировано для WASM, я довольно застрял, чтобы понять, в чем проблема.>

Подробнее здесь: https://stackoverflow.com/questions/794 ... -of-bounds
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»