Skip to content

Instantly share code, notes, and snippets.

@chaosgoo
Created March 3, 2026 04:45
Show Gist options
  • Select an option

  • Save chaosgoo/108e0bf265788a4551a9651ba194fef7 to your computer and use it in GitHub Desktop.

Select an option

Save chaosgoo/108e0bf265788a4551a9651ba194fef7 to your computer and use it in GitHub Desktop.
Flutter ffi调用lib3mf库解析3mf文件信息
#include <algorithm>
#include <iostream>
#include <lib3mf_implicit.hpp>
#include <string>
using namespace Lib3MF;
#ifdef __ANDROID__
#include <android/log.h>
#define LOG_TAG "NativeLib3mf"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#else
#include <cstdio>
#define LOGI(...) \
printf(__VA_ARGS__); \
printf("\n")
#endif
#include "native_lib3mf.h"
void printVersion(PWrapper wrapper) {
Lib3MF_uint32 nMajor, nMinor, nMicro;
wrapper->GetLibraryVersion(nMajor, nMinor, nMicro);
// 获取预发布和构建信息
std::string sReleaseInfo, sBuildInfo;
bool hasRelease = wrapper->GetPrereleaseInformation(sReleaseInfo);
bool hasBuild = wrapper->GetBuildInformation(sBuildInfo);
// 格式化输出
if (hasRelease && hasBuild) {
LOGI("lib3mf version = %u.%u.%u-%s+%s", nMajor, nMinor, nMicro,
sReleaseInfo.c_str(), sBuildInfo.c_str());
} else if (hasRelease) {
LOGI("lib3mf version = %u.%u.%u-%s", nMajor, nMinor, nMicro,
sReleaseInfo.c_str());
} else if (hasBuild) {
LOGI("lib3mf version = %u.%u.%u+%s", nMajor, nMinor, nMicro,
sBuildInfo.c_str());
} else {
LOGI("lib3mf version = %u.%u.%u", nMajor, nMinor, nMicro);
}
}
extern "C" {
void ShowTransform(sLib3MFTransform transform, std::string indent) {
LOGI("Transformation: [ %f %f %f %f ]", transform.m_Fields[0][0],
transform.m_Fields[1][0], transform.m_Fields[2][0],
transform.m_Fields[3][0]);
LOGI(" [ %f %f %f %f ]", transform.m_Fields[0][1],
transform.m_Fields[1][1], transform.m_Fields[2][1],
transform.m_Fields[3][1]);
LOGI(" [ %f %f %f %f ]", transform.m_Fields[0][2],
transform.m_Fields[1][2], transform.m_Fields[2][2],
transform.m_Fields[3][2]);
}
void ShowSliceStack(PSliceStack sliceStack, std::string indent) {
LOGI("%sSliceStackID: %u", indent.c_str(), sliceStack->GetResourceID());
if (sliceStack->GetSliceCount() > 0) {
LOGI("%s Slice count: %lu", indent.c_str(), sliceStack->GetSliceCount());
}
if (sliceStack->GetSliceRefCount() > 0) {
LOGI("%s Slice ref count: %lu", indent.c_str(),
sliceStack->GetSliceRefCount());
for (Lib3MF_uint64 iSliceRef = 0;
iSliceRef < sliceStack->GetSliceRefCount(); iSliceRef++) {
LOGI("%s Slice ref : %u", indent.c_str(),
sliceStack->GetSliceStackReference(iSliceRef)->GetResourceID());
}
}
}
void ShowThumbnailInformation(PModel model) {
/*
// TODO: this is not yet implemented in Lib3MF
*/
}
void ShowMetaDataInformation(PMetaDataGroup metaDataGroup) {
Lib3MF_uint32 nMetaDataCount = metaDataGroup->GetMetaDataCount();
for (Lib3MF_uint32 iMeta = 0; iMeta < nMetaDataCount; iMeta++) {
PMetaData metaData = metaDataGroup->GetMetaData(iMeta);
std::string sMetaDataValue = metaData->GetValue();
std::string sMetaDataName = metaData->GetName();
LOGI(" Metadatum %u: Name = \"%s\", Value = \"%s\"", iMeta,
sMetaDataName.c_str(), sMetaDataValue.c_str());
}
}
void ShowObjectProperties(PObject object) {
LOGI(" Name: \"%s\"", object->GetName().c_str());
LOGI(" PartNumber: \"%s\"", object->GetPartNumber().c_str());
switch (object->GetType()) {
case eObjectType::Model:
LOGI(" Object type: model");
break;
case eObjectType::Support:
LOGI(" Object type: support");
break;
case eObjectType::SolidSupport:
LOGI(" Object type: solidsupport");
break;
case eObjectType::Other:
LOGI(" Object type: other");
break;
default:
LOGI(" Object type: invalid");
break;
}
if (object->HasSlices(false)) {
PSliceStack sliceStack = object->GetSliceStack();
ShowSliceStack(sliceStack, " ");
}
if (object->GetMetaDataGroup()->GetMetaDataCount() > 0) {
ShowMetaDataInformation(object->GetMetaDataGroup());
}
}
void ShowComponentsObjectInformation(PComponentsObject componentsObject) {
LOGI("components object #%u: ", componentsObject->GetResourceID());
ShowObjectProperties(componentsObject);
LOGI(" Component count: %u", componentsObject->GetComponentCount());
for (Lib3MF_uint32 nIndex = 0; nIndex < componentsObject->GetComponentCount();
nIndex++) {
PComponent component = componentsObject->GetComponent(nIndex);
LOGI(" Component %u: Object ID: %u", nIndex,
component->GetObjectResourceID());
if (component->HasTransform()) {
ShowTransform(component->GetTransform(), " ");
} else {
LOGI(" Transformation: none");
}
}
}
void ShowMeshObjectInformation(PMeshObject meshObject) {
LOGI("mesh object #%u: ", meshObject->GetResourceID());
ShowObjectProperties(meshObject);
Lib3MF_uint64 nVertexCount = meshObject->GetVertexCount();
Lib3MF_uint64 nTriangleCount = meshObject->GetTriangleCount();
PBeamLattice beamLattice = meshObject->BeamLattice();
// Output data
LOGI(" Vertex count: %lu", nVertexCount);
LOGI(" Triangle count: %lu", nTriangleCount);
Lib3MF_uint64 nBeamCount = beamLattice->GetBeamCount();
if (nBeamCount > 0) {
LOGI(" Beam count: %lu", nBeamCount);
Lib3MF_uint32 nRepresentationMesh;
if (beamLattice->GetRepresentation(nRepresentationMesh))
LOGI(" |_Representation Mesh ID: %u", nRepresentationMesh);
eLib3MFBeamLatticeClipMode eClipMode;
Lib3MF_uint32 nClippingMesh;
beamLattice->GetClipping(eClipMode, nClippingMesh);
if (eClipMode != eBeamLatticeClipMode::NoClipMode)
LOGI(" |_Clipping Mesh ID: %u (mode=%d)", nClippingMesh,
(int)eClipMode);
if (beamLattice->GetBeamSetCount() > 0) {
LOGI(" |_BeamSet count: %u", beamLattice->GetBeamSetCount());
}
}
}
FFI_PLUGIN_EXPORT int32_t extract_info(const char* path) {
PWrapper wrapper = CWrapper::loadLibrary();
LOGI("------------------------------------------------------------------");
LOGI("3MF Read example");
printVersion(wrapper);
LOGI("------------------------------------------------------------------");
PModel model = wrapper->CreateModel();
// Import Model from 3MF File
{
PReader reader = model->QueryReader("3mf");
// And deactivate the strict mode (default is "false", anyway. This just
// demonstrates where/how to use it).
reader->SetStrictModeActive(false);
LOGI("ReadFromFile:");
LOGI("%s", path);
reader->ReadFromFile(path);
for (Lib3MF_uint32 iWarning = 0; iWarning < reader->GetWarningCount();
iWarning++) {
Lib3MF_uint32 nErrorCode;
std::string sWarningMessage = reader->GetWarning(iWarning, nErrorCode);
LOGI("Encountered warning #%u : %s", nErrorCode, sWarningMessage.c_str());
}
}
ShowThumbnailInformation(model);
ShowMetaDataInformation(model->GetMetaDataGroup());
PSliceStackIterator sliceStacks = model->GetSliceStacks();
while (sliceStacks->MoveNext()) {
PSliceStack sliceStack = sliceStacks->GetCurrentSliceStack();
ShowSliceStack(sliceStack, "");
}
PObjectIterator objectIterator = model->GetObjects();
while (objectIterator->MoveNext()) {
PObject object = objectIterator->GetCurrentObject();
if (object->IsMeshObject()) {
ShowMeshObjectInformation(
model->GetMeshObjectByID(object->GetResourceID()));
} else if (object->IsComponentsObject()) {
ShowComponentsObjectInformation(
model->GetComponentsObjectByID(object->GetResourceID()));
} else {
LOGI("unknown object #%u", object->GetResourceID());
}
}
PBuildItemIterator buildItemIterator = model->GetBuildItems();
while (buildItemIterator->MoveNext()) {
PBuildItem buildItem = buildItemIterator->GetCurrent();
LOGI("Build item (Object #%u): ", buildItem->GetObjectResourceID());
if (buildItem->HasObjectTransform()) {
ShowTransform(buildItem->GetObjectTransform(), " ");
} else {
LOGI(" Transformation: none");
}
LOGI(" Part number: \"%s\"", buildItem->GetPartNumber().c_str());
if (buildItem->GetMetaDataGroup()->GetMetaDataCount() > 0) {
ShowMetaDataInformation(buildItem->GetMetaDataGroup());
}
}
LOGI("done");
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment