mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-19 06:41:14 -06:00
Add the full source of BambuStudio
using version 1.0.10
This commit is contained in:
parent
30bcadab3e
commit
1555904bef
3771 changed files with 1251328 additions and 0 deletions
549
xs/src/perlglue.cpp
Normal file
549
xs/src/perlglue.cpp
Normal file
|
@ -0,0 +1,549 @@
|
|||
#ifdef SLIC3RXS
|
||||
#include <xsinit.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
REGISTER_CLASS(ExPolygon, "ExPolygon");
|
||||
REGISTER_CLASS(ExPolygonCollection, "ExPolygon::Collection");
|
||||
REGISTER_CLASS(ExtrusionMultiPath, "ExtrusionMultiPath");
|
||||
REGISTER_CLASS(ExtrusionPath, "ExtrusionPath");
|
||||
REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop");
|
||||
REGISTER_CLASS(ExtrusionEntityCollection, "ExtrusionPath::Collection");
|
||||
REGISTER_CLASS(ExtrusionSimulator, "ExtrusionSimulator");
|
||||
REGISTER_CLASS(Filler, "Filler");
|
||||
REGISTER_CLASS(Flow, "Flow");
|
||||
REGISTER_CLASS(CoolingBuffer, "GCode::CoolingBuffer");
|
||||
REGISTER_CLASS(GCode, "GCode");
|
||||
REGISTER_CLASS(Layer, "Layer");
|
||||
REGISTER_CLASS(SupportLayer, "Layer::Support");
|
||||
REGISTER_CLASS(LayerRegion, "Layer::Region");
|
||||
REGISTER_CLASS(Line, "Line");
|
||||
REGISTER_CLASS(Linef3, "Linef3");
|
||||
REGISTER_CLASS(PerimeterGenerator, "Layer::PerimeterGenerator");
|
||||
REGISTER_CLASS(PlaceholderParser, "GCode::PlaceholderParser");
|
||||
REGISTER_CLASS(Polygon, "Polygon");
|
||||
REGISTER_CLASS(Polyline, "Polyline");
|
||||
REGISTER_CLASS(PolylineCollection, "Polyline::Collection");
|
||||
REGISTER_CLASS(Print, "Print");
|
||||
REGISTER_CLASS(PrintObject, "Print::Object");
|
||||
REGISTER_CLASS(PrintRegion, "Print::Region");
|
||||
REGISTER_CLASS(Model, "Model");
|
||||
REGISTER_CLASS(ModelMaterial, "Model::Material");
|
||||
REGISTER_CLASS(ModelObject, "Model::Object");
|
||||
REGISTER_CLASS(ModelVolume, "Model::Volume");
|
||||
REGISTER_CLASS(ModelInstance, "Model::Instance");
|
||||
REGISTER_CLASS(BoundingBox, "Geometry::BoundingBox");
|
||||
REGISTER_CLASS(BoundingBoxf, "Geometry::BoundingBoxf");
|
||||
REGISTER_CLASS(BoundingBoxf3, "Geometry::BoundingBoxf3");
|
||||
REGISTER_CLASS(BridgeDetector, "BridgeDetector");
|
||||
REGISTER_CLASS(Point, "Point");
|
||||
__REGISTER_CLASS(Vec2d, "Pointf");
|
||||
__REGISTER_CLASS(Vec3d, "Pointf3");
|
||||
REGISTER_CLASS(DynamicPrintConfig, "Config");
|
||||
REGISTER_CLASS(StaticPrintConfig, "Config::Static");
|
||||
REGISTER_CLASS(PrintObjectConfig, "Config::PrintObject");
|
||||
REGISTER_CLASS(PrintRegionConfig, "Config::PrintRegion");
|
||||
REGISTER_CLASS(GCodeConfig, "Config::GCode");
|
||||
REGISTER_CLASS(PrintConfig, "Config::Print");
|
||||
REGISTER_CLASS(FullPrintConfig, "Config::Full");
|
||||
REGISTER_CLASS(Surface, "Surface");
|
||||
REGISTER_CLASS(SurfaceCollection, "Surface::Collection");
|
||||
REGISTER_CLASS(PrintObjectSupportMaterial, "Print::SupportMaterial2");
|
||||
REGISTER_CLASS(TriangleMesh, "TriangleMesh");
|
||||
|
||||
SV* ConfigBase__as_hash(ConfigBase* THIS)
|
||||
{
|
||||
HV* hv = newHV();
|
||||
for (auto &key : THIS->keys())
|
||||
(void)hv_store(hv, key.c_str(), key.length(), ConfigBase__get(THIS, key), 0);
|
||||
return newRV_noinc((SV*)hv);
|
||||
}
|
||||
|
||||
SV* ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key)
|
||||
{
|
||||
ConfigOption *opt = THIS->option(opt_key, false);
|
||||
return (opt == nullptr) ?
|
||||
&PL_sv_undef :
|
||||
ConfigOption_to_SV(*opt, *THIS->def()->get(opt_key));
|
||||
}
|
||||
|
||||
SV* ConfigOption_to_SV(const ConfigOption &opt, const ConfigOptionDef &def)
|
||||
{
|
||||
switch (def.type) {
|
||||
case coFloat:
|
||||
case coPercent:
|
||||
return newSVnv(static_cast<const ConfigOptionFloat*>(&opt)->value);
|
||||
case coFloats:
|
||||
case coPercents:
|
||||
{
|
||||
auto optv = static_cast<const ConfigOptionFloats*>(&opt);
|
||||
AV* av = newAV();
|
||||
av_fill(av, optv->values.size()-1);
|
||||
for (const double &v : optv->values)
|
||||
av_store(av, &v - optv->values.data(), newSVnv(v));
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
case coInt:
|
||||
return newSViv(static_cast<const ConfigOptionInt*>(&opt)->value);
|
||||
case coInts:
|
||||
{
|
||||
auto optv = static_cast<const ConfigOptionInts*>(&opt);
|
||||
AV* av = newAV();
|
||||
av_fill(av, optv->values.size()-1);
|
||||
for (const int &v : optv->values)
|
||||
av_store(av, &v - optv->values.data(), newSViv(v));
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
case coString:
|
||||
{
|
||||
auto optv = static_cast<const ConfigOptionString*>(&opt);
|
||||
// we don't serialize() because that would escape newlines
|
||||
return newSVpvn_utf8(optv->value.c_str(), optv->value.length(), true);
|
||||
}
|
||||
case coStrings:
|
||||
{
|
||||
auto optv = static_cast<const ConfigOptionStrings*>(&opt);
|
||||
AV* av = newAV();
|
||||
av_fill(av, optv->values.size()-1);
|
||||
for (const std::string &v : optv->values)
|
||||
av_store(av, &v - optv->values.data(), newSVpvn_utf8(v.c_str(), v.length(), true));
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
case coPoint:
|
||||
return perl_to_SV_clone_ref(static_cast<const ConfigOptionPoint*>(&opt)->value);
|
||||
case coPoint3:
|
||||
return perl_to_SV_clone_ref(static_cast<const ConfigOptionPoint3*>(&opt)->value);
|
||||
case coPoints:
|
||||
{
|
||||
auto optv = static_cast<const ConfigOptionPoints*>(&opt);
|
||||
AV* av = newAV();
|
||||
av_fill(av, optv->values.size()-1);
|
||||
for (const Vec2d &v : optv->values)
|
||||
av_store(av, &v - optv->values.data(), perl_to_SV_clone_ref(v));
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
case coBool:
|
||||
return newSViv(static_cast<const ConfigOptionBool*>(&opt)->value ? 1 : 0);
|
||||
case coBools:
|
||||
{
|
||||
auto optv = static_cast<const ConfigOptionBools*>(&opt);
|
||||
AV* av = newAV();
|
||||
av_fill(av, optv->values.size()-1);
|
||||
for (size_t i = 0; i < optv->values.size(); ++ i)
|
||||
av_store(av, i, newSViv(optv->values[i] ? 1 : 0));
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
default:
|
||||
std::string serialized = opt.serialize();
|
||||
return newSVpvn_utf8(serialized.c_str(), serialized.length(), true);
|
||||
}
|
||||
}
|
||||
|
||||
SV* ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t i)
|
||||
{
|
||||
ConfigOption* opt = THIS->option(opt_key, false);
|
||||
if (opt == nullptr)
|
||||
return &PL_sv_undef;
|
||||
|
||||
const ConfigOptionDef* def = THIS->def()->get(opt_key);
|
||||
switch (def->type) {
|
||||
case coFloats:
|
||||
case coPercents:
|
||||
return newSVnv(static_cast<ConfigOptionFloats*>(opt)->get_at(i));
|
||||
case coInts:
|
||||
return newSViv(static_cast<ConfigOptionInts*>(opt)->get_at(i));
|
||||
case coStrings:
|
||||
{
|
||||
// we don't serialize() because that would escape newlines
|
||||
const std::string &val = static_cast<ConfigOptionStrings*>(opt)->get_at(i);
|
||||
return newSVpvn_utf8(val.c_str(), val.length(), true);
|
||||
}
|
||||
case coPoints:
|
||||
return perl_to_SV_clone_ref(static_cast<ConfigOptionPoints*>(opt)->get_at(i));
|
||||
case coBools:
|
||||
return newSViv(static_cast<ConfigOptionBools*>(opt)->get_at(i) ? 1 : 0);
|
||||
default:
|
||||
return &PL_sv_undef;
|
||||
}
|
||||
}
|
||||
|
||||
bool ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value)
|
||||
{
|
||||
ConfigOption* opt = THIS->option(opt_key, true);
|
||||
if (opt == nullptr)
|
||||
CONFESS("Trying to set non-existing option");
|
||||
const ConfigOptionDef* def = THIS->def()->get(opt_key);
|
||||
if (opt->type() != def->type)
|
||||
CONFESS("Option type is different from the definition");
|
||||
switch (def->type) {
|
||||
case coFloat:
|
||||
if (!looks_like_number(value))
|
||||
return false;
|
||||
static_cast<ConfigOptionFloat*>(opt)->value = SvNV(value);
|
||||
break;
|
||||
case coFloats:
|
||||
{
|
||||
std::vector<double> &values = static_cast<ConfigOptionFloats*>(opt)->values;
|
||||
AV* av = (AV*)SvRV(value);
|
||||
const size_t len = av_len(av)+1;
|
||||
values.clear();
|
||||
values.reserve(len);
|
||||
for (size_t i = 0; i < len; ++ i) {
|
||||
SV** elem = av_fetch(av, i, 0);
|
||||
if (elem == NULL || !looks_like_number(*elem)) return false;
|
||||
values.emplace_back(SvNV(*elem));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case coPercents:
|
||||
{
|
||||
std::vector<double> &values = static_cast<ConfigOptionPercents*>(opt)->values;
|
||||
AV* av = (AV*)SvRV(value);
|
||||
const size_t len = av_len(av)+1;
|
||||
values.clear();
|
||||
values.reserve(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
SV** elem = av_fetch(av, i, 0);
|
||||
if (elem == NULL || !looks_like_number(*elem)) return false;
|
||||
values.emplace_back(SvNV(*elem));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case coInt:
|
||||
if (!looks_like_number(value)) return false;
|
||||
static_cast<ConfigOptionInt*>(opt)->value = SvIV(value);
|
||||
break;
|
||||
case coInts:
|
||||
{
|
||||
std::vector<int> &values = static_cast<ConfigOptionInts*>(opt)->values;
|
||||
AV* av = (AV*)SvRV(value);
|
||||
const size_t len = av_len(av)+1;
|
||||
values.clear();
|
||||
values.reserve(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
SV** elem = av_fetch(av, i, 0);
|
||||
if (elem == NULL || !looks_like_number(*elem)) return false;
|
||||
values.emplace_back(SvIV(*elem));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case coString:
|
||||
static_cast<ConfigOptionString*>(opt)->value = std::string(SvPV_nolen(value), SvCUR(value));
|
||||
break;
|
||||
case coStrings:
|
||||
{
|
||||
std::vector<std::string> &values = static_cast<ConfigOptionStrings*>(opt)->values;
|
||||
AV* av = (AV*)SvRV(value);
|
||||
const size_t len = av_len(av)+1;
|
||||
values.clear();
|
||||
values.reserve(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
SV** elem = av_fetch(av, i, 0);
|
||||
if (elem == NULL) return false;
|
||||
values.emplace_back(std::string(SvPV_nolen(*elem), SvCUR(*elem)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case coPoint:
|
||||
return from_SV_check(value, &static_cast<ConfigOptionPoint*>(opt)->value);
|
||||
// case coPoint3:
|
||||
// not gonna fix it, die Perl die!
|
||||
// return from_SV_check(value, &static_cast<ConfigOptionPoint3*>(opt)->value);
|
||||
case coPoints:
|
||||
{
|
||||
std::vector<Vec2d> &values = static_cast<ConfigOptionPoints*>(opt)->values;
|
||||
AV* av = (AV*)SvRV(value);
|
||||
const size_t len = av_len(av)+1;
|
||||
values.clear();
|
||||
values.reserve(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
SV** elem = av_fetch(av, i, 0);
|
||||
Vec2d point(Vec2d::Zero());
|
||||
if (elem == NULL || !from_SV_check(*elem, &point)) return false;
|
||||
values.emplace_back(point);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case coBool:
|
||||
static_cast<ConfigOptionBool*>(opt)->value = SvTRUE(value);
|
||||
break;
|
||||
case coBools:
|
||||
{
|
||||
std::vector<unsigned char> &values = static_cast<ConfigOptionBools*>(opt)->values;
|
||||
AV* av = (AV*)SvRV(value);
|
||||
const size_t len = av_len(av)+1;
|
||||
values.clear();
|
||||
values.reserve(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
SV** elem = av_fetch(av, i, 0);
|
||||
if (elem == NULL) return false;
|
||||
values.emplace_back(SvTRUE(*elem));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (! opt->deserialize(std::string(SvPV_nolen(value)), ForwardCompatibilitySubstitutionRule::Disable))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This method is implemented as a workaround for this typemap bug:
|
||||
https://rt.cpan.org/Public/Bug/Display.html?id=94110 */
|
||||
bool ConfigBase__set_deserialize(ConfigBase* THIS, const t_config_option_key &opt_key, SV* str)
|
||||
{
|
||||
size_t len;
|
||||
const char * c = SvPV(str, len);
|
||||
std::string value(c, len);
|
||||
ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable };
|
||||
return THIS->set_deserialize_nothrow(opt_key, value, ctxt);
|
||||
}
|
||||
|
||||
void ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value, bool deserialize)
|
||||
{
|
||||
if (THIS->has(opt_key))
|
||||
return;
|
||||
if (deserialize)
|
||||
ConfigBase__set_deserialize(THIS, opt_key, value);
|
||||
else
|
||||
ConfigBase__set(THIS, opt_key, value);
|
||||
}
|
||||
|
||||
bool StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value)
|
||||
{
|
||||
const ConfigOptionDef* optdef = THIS->def()->get(opt_key);
|
||||
if (optdef->shortcut.empty())
|
||||
return ConfigBase__set(THIS, opt_key, value);
|
||||
for (const t_config_option_key &key : optdef->shortcut)
|
||||
if (! StaticConfig__set(THIS, key, value))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
SV* to_AV(ExPolygon* expolygon)
|
||||
{
|
||||
const unsigned int num_holes = expolygon->holes.size();
|
||||
AV* av = newAV();
|
||||
av_extend(av, num_holes); // -1 +1
|
||||
|
||||
av_store(av, 0, perl_to_SV_ref(expolygon->contour));
|
||||
|
||||
for (unsigned int i = 0; i < num_holes; i++) {
|
||||
av_store(av, i+1, perl_to_SV_ref(expolygon->holes[i]));
|
||||
}
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
|
||||
SV* to_SV_pureperl(const ExPolygon* expolygon)
|
||||
{
|
||||
const unsigned int num_holes = expolygon->holes.size();
|
||||
AV* av = newAV();
|
||||
av_extend(av, num_holes); // -1 +1
|
||||
av_store(av, 0, to_SV_pureperl(&expolygon->contour));
|
||||
for (unsigned int i = 0; i < num_holes; i++) {
|
||||
av_store(av, i+1, to_SV_pureperl(&expolygon->holes[i]));
|
||||
}
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
|
||||
void from_SV(SV* expoly_sv, ExPolygon* expolygon)
|
||||
{
|
||||
AV* expoly_av = (AV*)SvRV(expoly_sv);
|
||||
const unsigned int num_polygons = av_len(expoly_av)+1;
|
||||
expolygon->holes.resize(num_polygons-1);
|
||||
|
||||
SV** polygon_sv = av_fetch(expoly_av, 0, 0);
|
||||
from_SV(*polygon_sv, &expolygon->contour);
|
||||
for (unsigned int i = 0; i < num_polygons-1; i++) {
|
||||
polygon_sv = av_fetch(expoly_av, i+1, 0);
|
||||
from_SV(*polygon_sv, &expolygon->holes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void from_SV_check(SV* expoly_sv, ExPolygon* expolygon)
|
||||
{
|
||||
if (sv_isobject(expoly_sv) && (SvTYPE(SvRV(expoly_sv)) == SVt_PVMG)) {
|
||||
if (!sv_isa(expoly_sv, perl_class_name(expolygon)) && !sv_isa(expoly_sv, perl_class_name_ref(expolygon)))
|
||||
CONFESS("Not a valid %s object", perl_class_name(expolygon));
|
||||
// a XS ExPolygon was supplied
|
||||
*expolygon = *(ExPolygon *)SvIV((SV*)SvRV( expoly_sv ));
|
||||
} else {
|
||||
// a Perl arrayref was supplied
|
||||
from_SV(expoly_sv, expolygon);
|
||||
}
|
||||
}
|
||||
|
||||
void from_SV(SV* line_sv, Line* THIS)
|
||||
{
|
||||
AV* line_av = (AV*)SvRV(line_sv);
|
||||
from_SV_check(*av_fetch(line_av, 0, 0), &THIS->a);
|
||||
from_SV_check(*av_fetch(line_av, 1, 0), &THIS->b);
|
||||
}
|
||||
|
||||
void from_SV_check(SV* line_sv, Line* THIS)
|
||||
{
|
||||
if (sv_isobject(line_sv) && (SvTYPE(SvRV(line_sv)) == SVt_PVMG)) {
|
||||
if (!sv_isa(line_sv, perl_class_name(THIS)) && !sv_isa(line_sv, perl_class_name_ref(THIS)))
|
||||
CONFESS("Not a valid %s object", perl_class_name(THIS));
|
||||
*THIS = *(Line*)SvIV((SV*)SvRV( line_sv ));
|
||||
} else {
|
||||
from_SV(line_sv, THIS);
|
||||
}
|
||||
}
|
||||
|
||||
SV* to_AV(Line* THIS)
|
||||
{
|
||||
AV* av = newAV();
|
||||
av_extend(av, 1);
|
||||
|
||||
av_store(av, 0, perl_to_SV_ref(THIS->a));
|
||||
av_store(av, 1, perl_to_SV_ref(THIS->b));
|
||||
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
|
||||
SV* to_SV_pureperl(const Line* THIS)
|
||||
{
|
||||
AV* av = newAV();
|
||||
av_extend(av, 1);
|
||||
av_store(av, 0, to_SV_pureperl(&THIS->a));
|
||||
av_store(av, 1, to_SV_pureperl(&THIS->b));
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
|
||||
void from_SV(SV* poly_sv, MultiPoint* THIS)
|
||||
{
|
||||
AV* poly_av = (AV*)SvRV(poly_sv);
|
||||
const unsigned int num_points = av_len(poly_av)+1;
|
||||
THIS->points.resize(num_points);
|
||||
|
||||
for (unsigned int i = 0; i < num_points; i++) {
|
||||
SV** point_sv = av_fetch(poly_av, i, 0);
|
||||
from_SV_check(*point_sv, &THIS->points[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void from_SV_check(SV* poly_sv, MultiPoint* THIS)
|
||||
{
|
||||
if (sv_isobject(poly_sv) && (SvTYPE(SvRV(poly_sv)) == SVt_PVMG)) {
|
||||
*THIS = *(MultiPoint*)SvIV((SV*)SvRV( poly_sv ));
|
||||
} else {
|
||||
from_SV(poly_sv, THIS);
|
||||
}
|
||||
}
|
||||
|
||||
SV* to_AV(MultiPoint* THIS)
|
||||
{
|
||||
const unsigned int num_points = THIS->points.size();
|
||||
AV* av = newAV();
|
||||
if (num_points > 0) av_extend(av, num_points-1);
|
||||
for (unsigned int i = 0; i < num_points; i++) {
|
||||
av_store(av, i, perl_to_SV_ref(THIS->points[i]));
|
||||
}
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
|
||||
SV* to_SV_pureperl(const MultiPoint* THIS)
|
||||
{
|
||||
const unsigned int num_points = THIS->points.size();
|
||||
AV* av = newAV();
|
||||
if (num_points > 0) av_extend(av, num_points-1);
|
||||
for (unsigned int i = 0; i < num_points; i++) {
|
||||
av_store(av, i, to_SV_pureperl(&THIS->points[i]));
|
||||
}
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
|
||||
void from_SV_check(SV* poly_sv, Polygon* THIS)
|
||||
{
|
||||
if (sv_isobject(poly_sv) && !sv_isa(poly_sv, perl_class_name(THIS)) && !sv_isa(poly_sv, perl_class_name_ref(THIS)))
|
||||
CONFESS("Not a valid %s object", perl_class_name(THIS));
|
||||
|
||||
from_SV_check(poly_sv, (MultiPoint*)THIS);
|
||||
}
|
||||
|
||||
void from_SV_check(SV* poly_sv, Polyline* THIS)
|
||||
{
|
||||
if (!sv_isa(poly_sv, perl_class_name(THIS)) && !sv_isa(poly_sv, perl_class_name_ref(THIS)))
|
||||
CONFESS("Not a valid %s object", perl_class_name(THIS));
|
||||
|
||||
from_SV_check(poly_sv, (MultiPoint*)THIS);
|
||||
}
|
||||
|
||||
SV* to_SV_pureperl(const Point* THIS)
|
||||
{
|
||||
AV* av = newAV();
|
||||
av_fill(av, 1);
|
||||
av_store(av, 0, newSViv((*THIS)(0)));
|
||||
av_store(av, 1, newSViv((*THIS)(1)));
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
|
||||
void from_SV(SV* point_sv, Point* point)
|
||||
{
|
||||
AV* point_av = (AV*)SvRV(point_sv);
|
||||
// get a double from Perl and round it, otherwise
|
||||
// it would get truncated
|
||||
(*point) = Point(SvNV(*av_fetch(point_av, 0, 0)), SvNV(*av_fetch(point_av, 1, 0)));
|
||||
}
|
||||
|
||||
void from_SV_check(SV* point_sv, Point* point)
|
||||
{
|
||||
if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) {
|
||||
if (!sv_isa(point_sv, perl_class_name(point)) && !sv_isa(point_sv, perl_class_name_ref(point)))
|
||||
CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point_sv))));
|
||||
*point = *(Point*)SvIV((SV*)SvRV( point_sv ));
|
||||
} else {
|
||||
from_SV(point_sv, point);
|
||||
}
|
||||
}
|
||||
|
||||
SV* to_SV_pureperl(const Vec2d* point)
|
||||
{
|
||||
AV* av = newAV();
|
||||
av_fill(av, 1);
|
||||
av_store(av, 0, newSVnv((*point)(0)));
|
||||
av_store(av, 1, newSVnv((*point)(1)));
|
||||
return newRV_noinc((SV*)av);
|
||||
}
|
||||
|
||||
bool from_SV(SV* point_sv, Vec2d* point)
|
||||
{
|
||||
AV* point_av = (AV*)SvRV(point_sv);
|
||||
SV* sv_x = *av_fetch(point_av, 0, 0);
|
||||
SV* sv_y = *av_fetch(point_av, 1, 0);
|
||||
if (!looks_like_number(sv_x) || !looks_like_number(sv_y)) return false;
|
||||
|
||||
*point = Vec2d(SvNV(sv_x), SvNV(sv_y));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool from_SV_check(SV* point_sv, Vec2d* point)
|
||||
{
|
||||
if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) {
|
||||
if (!sv_isa(point_sv, perl_class_name(point)) && !sv_isa(point_sv, perl_class_name_ref(point)))
|
||||
CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point_sv))));
|
||||
*point = *(Vec2d*)SvIV((SV*)SvRV( point_sv ));
|
||||
return true;
|
||||
} else {
|
||||
return from_SV(point_sv, point);
|
||||
}
|
||||
}
|
||||
|
||||
void from_SV_check(SV* surface_sv, Surface* THIS)
|
||||
{
|
||||
if (!sv_isa(surface_sv, perl_class_name(THIS)) && !sv_isa(surface_sv, perl_class_name_ref(THIS)))
|
||||
CONFESS("Not a valid %s object", perl_class_name(THIS));
|
||||
// a XS Surface was supplied
|
||||
*THIS = *(Surface *)SvIV((SV*)SvRV( surface_sv ));
|
||||
}
|
||||
|
||||
SV* to_SV(TriangleMesh* THIS)
|
||||
{
|
||||
SV* sv = newSV(0);
|
||||
sv_setref_pv( sv, perl_class_name(THIS), (void*)THIS );
|
||||
return sv;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
7063
xs/src/ppport.h
Normal file
7063
xs/src/ppport.h
Normal file
File diff suppressed because it is too large
Load diff
259
xs/src/xsinit.h
Normal file
259
xs/src/xsinit.h
Normal file
|
@ -0,0 +1,259 @@
|
|||
#ifndef _xsinit_h_
|
||||
#define _xsinit_h_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable some obnoxious warnings given by Visual Studio with the default warning level 4.
|
||||
#pragma warning(disable: 4100 4127 4189 4244 4267 4700 4702 4800)
|
||||
#endif
|
||||
|
||||
// undef some macros set by Perl which cause compilation errors on Win32
|
||||
#undef read
|
||||
#undef seekdir
|
||||
#undef bind
|
||||
#undef send
|
||||
#undef connect
|
||||
#undef wait
|
||||
#undef accept
|
||||
#undef close
|
||||
#undef open
|
||||
#undef write
|
||||
#undef socket
|
||||
#undef listen
|
||||
#undef shutdown
|
||||
#undef ioctl
|
||||
#undef getpeername
|
||||
#undef rect
|
||||
#undef setsockopt
|
||||
#undef getsockopt
|
||||
#undef getsockname
|
||||
#undef gethostname
|
||||
#undef select
|
||||
#undef socketpair
|
||||
#undef recvfrom
|
||||
#undef sendto
|
||||
#undef pause
|
||||
|
||||
// these need to be included early for Win32 (listing it in Build.PL is not enough)
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
// #include <libslic3r.h>
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
// extern "C" {
|
||||
#include "EXTERN.h"
|
||||
#include "perl.h"
|
||||
#include "XSUB.h"
|
||||
#include "ppport.h"
|
||||
#undef do_open
|
||||
#undef do_close
|
||||
#undef bind
|
||||
#undef seed
|
||||
#undef push
|
||||
#undef pop
|
||||
#ifdef _MSC_VER
|
||||
// Undef some of the macros set by Perl <xsinit.h>, which cause compilation errors on Win32
|
||||
#undef connect
|
||||
#undef link
|
||||
#undef unlink
|
||||
#undef seek
|
||||
#undef send
|
||||
#undef write
|
||||
#undef open
|
||||
#undef close
|
||||
#undef seekdir
|
||||
#undef setbuf
|
||||
#undef fread
|
||||
#undef fseek
|
||||
#undef fputc
|
||||
#undef fwrite
|
||||
#undef fclose
|
||||
#undef sleep
|
||||
#undef snprintf
|
||||
#undef strerror
|
||||
#undef test
|
||||
#undef times
|
||||
#undef accept
|
||||
#undef wait
|
||||
#undef abort
|
||||
|
||||
// Breaks compilation with Eigen matrices embedded into Slic3r::Point.
|
||||
#undef malloc
|
||||
#undef realloc
|
||||
#undef free
|
||||
#undef select
|
||||
|
||||
// Because of TBB
|
||||
#define _WIN32_WINNT 0x0502
|
||||
#endif /* _MSC_VER */
|
||||
#undef Zero
|
||||
#undef Packet
|
||||
#undef _
|
||||
// }
|
||||
#endif
|
||||
|
||||
#include <ClipperUtils.hpp>
|
||||
#include <Config.hpp>
|
||||
#include <ExPolygon.hpp>
|
||||
#include <MultiPoint.hpp>
|
||||
#include <Point.hpp>
|
||||
#include <Polygon.hpp>
|
||||
#include <Polyline.hpp>
|
||||
#include <TriangleMesh.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
template<class T>
|
||||
struct ClassTraits {
|
||||
// Name of a Perl alias of a C++ class type, owned by Perl, reference counted.
|
||||
static const char* name;
|
||||
// Name of a Perl alias of a C++ class type, owned by the C++ code.
|
||||
// The references shall be enumerated at the end of XS.pm, where the desctructor is undefined with sub DESTROY {},
|
||||
// so Perl will never delete the object instance.
|
||||
static const char* name_ref;
|
||||
};
|
||||
|
||||
// use this for typedefs for which the forward prototype
|
||||
// in REGISTER_CLASS won't work
|
||||
#define __REGISTER_CLASS(cname, perlname) \
|
||||
template <>const char* ClassTraits<cname>::name = "Slic3r::" perlname; \
|
||||
template <>const char* ClassTraits<cname>::name_ref = "Slic3r::" perlname "::Ref";
|
||||
|
||||
#define REGISTER_CLASS(cname,perlname) \
|
||||
class cname; \
|
||||
__REGISTER_CLASS(cname, perlname);
|
||||
|
||||
// Return Perl alias to a C++ class name.
|
||||
template<class T>
|
||||
const char* perl_class_name(const T*) { return ClassTraits<T>::name; }
|
||||
// Return Perl alias to a C++ class name, suffixed with ::Ref.
|
||||
// Such a C++ class instance will not be destroyed by Perl, the instance destruction is left to the C++ code.
|
||||
template<class T>
|
||||
const char* perl_class_name_ref(const T*) { return ClassTraits<T>::name_ref; }
|
||||
|
||||
// Mark the Perl SV (Scalar Value) as owning a "blessed" pointer to an object reference.
|
||||
// Perl will never release the C++ instance.
|
||||
template<class T>
|
||||
SV* perl_to_SV_ref(T &t) {
|
||||
SV* sv = newSV(0);
|
||||
sv_setref_pv( sv, perl_class_name_ref(&t), &t );
|
||||
return sv;
|
||||
}
|
||||
|
||||
// Mark the Perl SV (Scalar Value) as owning a "blessed" pointer to an object instance.
|
||||
// Perl will own the C++ instance, therefore it will also release it.
|
||||
template<class T>
|
||||
SV* perl_to_SV_clone_ref(const T &t) {
|
||||
SV* sv = newSV(0);
|
||||
sv_setref_pv( sv, perl_class_name(&t), new T(t) );
|
||||
return sv;
|
||||
}
|
||||
|
||||
// Reference wrapper to provide a C++ instance to Perl while keeping Perl from destroying the instance.
|
||||
// The instance is created temporarily by XS.cpp just to provide Perl with a CLASS name and a object instance pointer.
|
||||
template <class T>
|
||||
class Ref {
|
||||
T* val;
|
||||
public:
|
||||
Ref() : val(NULL) {}
|
||||
Ref(T* t) : val(t) {}
|
||||
Ref(const T* t) : val(const_cast<T*>(t)) {}
|
||||
// Called by XS.cpp to convert the referenced object instance to a Perl SV, before it is blessed with the name
|
||||
// returned by CLASS()
|
||||
operator T*() const { return val; }
|
||||
// Name to bless the Perl SV with. The name ends with a "::Ref" suffix to keep Perl from destroying the object instance.
|
||||
static const char* CLASS() { return ClassTraits<T>::name_ref; }
|
||||
};
|
||||
|
||||
// Wrapper to clone a C++ object instance before passing it to Perl for ownership.
|
||||
// This wrapper instance is created temporarily by XS.cpp to provide Perl with a CLASS name and a object instance pointer.
|
||||
template <class T>
|
||||
class Clone {
|
||||
T* val;
|
||||
public:
|
||||
Clone() : val(NULL) {}
|
||||
Clone(T* t) : val(new T(*t)) {}
|
||||
Clone(const T& t) : val(new T(t)) {}
|
||||
// Called by XS.cpp to convert the cloned object instance to a Perl SV, before it is blessed with the name
|
||||
// returned by CLASS()
|
||||
operator T*() const { return val; }
|
||||
// Name to bless the Perl SV with. If there is a destructor registered in the XSP file for this class, then Perl will
|
||||
// call this destructor when the reference counter of this SV drops to zero.
|
||||
static const char* CLASS() { return ClassTraits<T>::name; }
|
||||
};
|
||||
|
||||
SV* ConfigBase__as_hash(ConfigBase* THIS);
|
||||
SV* ConfigOption_to_SV(const ConfigOption &opt, const ConfigOptionDef &def);
|
||||
SV* ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key);
|
||||
SV* ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t i);
|
||||
bool ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value);
|
||||
bool ConfigBase__set_deserialize(ConfigBase* THIS, const t_config_option_key &opt_key, SV* str);
|
||||
void ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value, bool deserialize = false);
|
||||
bool StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value);
|
||||
SV* to_AV(ExPolygon* expolygon);
|
||||
SV* to_SV_pureperl(const ExPolygon* expolygon);
|
||||
void from_SV(SV* expoly_sv, ExPolygon* expolygon);
|
||||
void from_SV_check(SV* expoly_sv, ExPolygon* expolygon);
|
||||
void from_SV(SV* line_sv, Line* THIS);
|
||||
void from_SV_check(SV* line_sv, Line* THIS);
|
||||
SV* to_AV(Line* THIS);
|
||||
SV* to_SV_pureperl(const Line* THIS);
|
||||
void from_SV(SV* poly_sv, MultiPoint* THIS);
|
||||
void from_SV_check(SV* poly_sv, MultiPoint* THIS);
|
||||
SV* to_AV(MultiPoint* THIS);
|
||||
SV* to_SV_pureperl(const MultiPoint* THIS);
|
||||
void from_SV_check(SV* poly_sv, Polygon* THIS);
|
||||
void from_SV_check(SV* poly_sv, Polyline* THIS);
|
||||
SV* to_SV_pureperl(const Point* THIS);
|
||||
void from_SV(SV* point_sv, Point* point);
|
||||
void from_SV_check(SV* point_sv, Point* point);
|
||||
SV* to_SV_pureperl(const Vec2d* point);
|
||||
bool from_SV(SV* point_sv, Vec2d* point);
|
||||
bool from_SV_check(SV* point_sv, Vec2d* point);
|
||||
void from_SV_check(SV* surface_sv, Surface* THIS);
|
||||
SV* to_SV(TriangleMesh* THIS);
|
||||
|
||||
}
|
||||
|
||||
// Defined in wxPerlIface.cpp
|
||||
// Return a pointer to the associated wxWidgets object instance given by classname.
|
||||
extern void* wxPli_sv_2_object( pTHX_ SV* scalar, const char* classname );
|
||||
|
||||
inline void confess_at(const char *file, int line, const char *func, const char *pat, ...)
|
||||
{
|
||||
#ifdef SLIC3RXS
|
||||
va_list args;
|
||||
SV *error_sv = newSVpvf("Error in function %s at %s:%d: ", func,
|
||||
file, line);
|
||||
|
||||
va_start(args, pat);
|
||||
sv_vcatpvf(error_sv, pat, &args);
|
||||
va_end(args);
|
||||
|
||||
sv_catpvn(error_sv, "\n\t", 2);
|
||||
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs( sv_2mortal(error_sv) );
|
||||
PUTBACK;
|
||||
call_pv("Carp::confess", G_DISCARD);
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFESS
|
||||
/* Implementation of CONFESS("foo"): */
|
||||
#ifdef _MSC_VER
|
||||
#define CONFESS(...) confess_at(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
|
||||
#else
|
||||
#define CONFESS(...) confess_at(__FILE__, __LINE__, __func__, __VA_ARGS__)
|
||||
#endif
|
||||
/* End implementation of CONFESS("foo"): */
|
||||
#endif /* CONFESS */
|
||||
|
||||
using namespace Slic3r;
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue