SketchUp C API
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
SketchUp C API

The SketchUp C API is an interface for reading and writing data to and from SketchUp models. This API interacts directly with SketchUp files (.skp). It can create new ones as well as read or modify existing ones.

SketchUp Importer/Exporter Interface

The SketchUp Importer/Exporter Interface allows you to create native SketchUp importer and exporter modules that are available directly within SketchUp as an import or export option.

SketchUp C API Documentation

The documentation contains reference material for all functions, data structures, and enumerations in both the SketchUp C API and the SketchUp Importer/Exporter interface.

The online C API documentation can be found here: SketchUp C API Online Documentation

Build and Release Considerations

Windows

The C API library for Windows is built using Microsoft Visual Studio 2019 (v142). It includes only 64-bit binaries. Building and releasing an application using the SketchUp C API for Windows requires including SketchUpAPI.dll and SketchUpCommonPreferences.dll, which can be found in the SketchUp C SDK for Windows. Also, the following C runtime DLLs must be included: msvcp140.dll and msvcr140.dll. Due to Microsoft binary compatibility, the runtime DLLs remain named "-v140.dll"

Alternatively the Microsoft Visual C++ 2019 Redistributable Packages can be used, which can be found here:

64-bit redistributable package

History

SketchUp 2017, 2018, and 2019 for Windows were built using Visual Studio 2015 SP1, and so plugins should be built with the Platform Toolset set to Visual Studio 2015 (v140). Using a different Platform Toolset will likely cause the plugin to fail to load and cause SketchUp to crash.

macOS

The SketchUp C API library for macOS is built using Xcode 10.3 (targeting SDK 10.12). Building and releasing an application using the SketchUp C API for macOS requires including SketchUpAPI.framework. The framework is 64-bit, and can be found in the SketchUp C SDK for macOS.

History

SketchUp 2017, 2018, and 2019 for macOS were built using Xcode 7.2.1 (SDK 10.10).

SketchUp 2017 for macOS was built using libstdc++, so plugins should be built with the same library. Using libc++ will likely cause the plugin to fail to load and cause SketchUp to crash.

Standalone vs Extension Usage

How you link depends on whether you are using the C API from a SketchUp extension reading from the open model or not.

Standalone Usage

This is the most typical usage for most cases:

Windows

macOS

Extension Usage (Live C API)

It is possible to use the C API for read only access to the open model via SUApplicationGetActiveModel.

Windows

macOS

For more details, refer to the Live C API example project: https://github.com/SketchUp/sketchup-live-c-api

Example Projects

Included in the SDK package are two C++ sample projects: skp_to_xml and xml_to_skp. These projects demonstrate how the SketchUp C API can be used within the SketchUp plugin architecture to create importers and exporters meant to be hosted directly by SketchUp. The XML schema used by the samples is only for demonstration purposes.

Quick Start

Below are some simple code examples of how to use the SketchUp C API in a standalone C++ program.

Reading from a .skp file

This example demonstrates how to load a SketchUp model from a .SKP file and read some data from it.

#include <vector>
int main() {
// Always initialize the API before using it
// Load the model from a file
SUResult res = SUModelCreateFromFileWithStatus(&model, "model.skp", &status);
// It's best to always check the return code from each SU function call.
// Only showing this check once to keep this example short.
if (res != SU_ERROR_NONE) {
std::cout << "Failed creating model from a file" << std::endl;
return 1;
}
std::cout
<< "This model was created in a more recent SketchUp version than that of the SDK. "
"It contains data which will not be read. Saving the model over the original file may "
"lead to permanent data loss."
<< std::endl;
}
// Get the entity container of the model.
SUModelGetEntities(model, &entities);
// Get all the faces from the entities object
size_t faceCount = 0;
SUEntitiesGetNumFaces(entities, &faceCount);
if (faceCount > 0) {
std::vector<SUFaceRef> faces(faceCount);
SUEntitiesGetFaces(entities, faceCount, &faces[0], &faceCount);
// Get all the edges in this face
for (size_t i = 0; i < faceCount; i++) {
size_t edgeCount = 0;
SUFaceGetNumEdges(faces[i], &edgeCount);
if (edgeCount > 0) {
std::vector<SUEdgeRef> edges(edgeCount);
SUFaceGetEdges(faces[i], edgeCount, &edges[0], &edgeCount);
// Get the vertex positions for each edge
for (size_t j = 0; j < edgeCount; j++) {
SUVertexRef startVertex = SU_INVALID;
SUVertexRef endVertex = SU_INVALID;
SUEdgeGetStartVertex(edges[j], &startVertex);
SUEdgeGetEndVertex(edges[j], &endVertex);
SUPoint3D start;
SUPoint3D end;
SUVertexGetPosition(startVertex, &start);
SUVertexGetPosition(endVertex, &end);
// Now do something with the point data
}
}
}
}
// Get model name
SUModelGetName(model, &name);
size_t name_length = 0;
SUStringGetUTF8Length(name, &name_length);
char* name_utf8 = new char[name_length + 1];
SUStringGetUTF8(name, name_length + 1, name_utf8, &name_length);
// Now we have the name in a form we can use
delete []name_utf8;
// Must release the model or there will be memory leaks
SUModelRelease(&model);
// Always terminate the API when done using it
return 0;
}

Writing to a .skp file

This example demonstrates how to create a SketchUp model, add some data to it, and then save the model to a .SKP file.

Warning
Geometry is not merged when it is added through the API except when using SUEntitiesFill(). For instance, when attempting to create a cube by creating and adding 6 faces using SUEntitiesAddFaces(), the duplicated edges will not be merged. Instead use SUGeometryInput and SUEntitiesFill().
#include <vector>
int main() {
// Always initialize the API before using it
// Create an empty model
SUResult res = SUModelCreate(&model);
// It's best to always check the return code from each SU function call.
// Only showing this check once to keep this example short.
if (res != SU_ERROR_NONE)
return 1;
// Get the entity container of the model
SUModelGetEntities(model, &entities);
// Create a loop input describing the vertex ordering for a face's outer loop
SULoopInputRef outer_loop = SU_INVALID;
SULoopInputCreate(&outer_loop);
for (size_t i = 0; i < 4; ++i) {
SULoopInputAddVertexIndex(outer_loop, i);
}
// Create the face
SUPoint3D vertices[4] = { { 0, 0, 0 },
{ 100, 100, 0 },
{ 100, 100, 100 },
{ 0, 0, 100 } };
SUFaceCreate(&face, vertices, &outer_loop);
// Add the face to the entities
SUEntitiesAddFaces(entities, 1, &face);
// Save the in-memory model to a file
SUModelSaveToFile(model, "new_model.skp");
// Must release the model or there will be memory leaks
SUModelRelease(&model);
// Always terminate the API when done using it
return 0;
}

Memory Management in the SketchUp C API

The SketchUp C API does not automatically track and dispose of objects that are created. The API is a C interface, and therefore there are technical limitations to memory management.

The general rule is that after an object is created using one of the SU*Create*() functions, the object should in some way be attached to the model data hierarchy.

Some object types can be retrieved directly from an existing object without explicitly calling a create function. In this case, you should not explicitly call the matching release function, as it is already attached to an object.

Rules for explicitly created objects

Add the object to an entities collection

An entities collection can be retrieved from a model, a component definition, or a group. Entities collections are never created explicitly–they are automatically created as part of another object. Objects that can be added to an entities collection are faces, edges, curves, groups, images and component instances, using one of the SUEntitiesAdd*() functions. These objects will be released automatically when the model is released.

The types of objects that can be added to an Entities collection are:

Example: If you create an edge using SUEdgeCreate(), the most common pattern is to then add the edge to the model or to an object's entities collection. Example code (return values ignored for brevity):

// Create the model object
SUModelCreate(&model);
// Get the model's entities collection
SUModelGetEntities(model, &entities);
// Create an edge
SUPoint3D point1 = {0.0, 0.0, 0.0};
SUPoint3D point2 = {10.0, 20.0, 30.0};
SUEdgeCreate(&edge, &point1, &point2);
SUEntitiesAddEdges(entities, 1, &edge);
// Now release the model, which automatically releases the edge

Attach the object directly to the model

Objects that can be added to a model are materials, component definitions, layers or scenes, using one of the SUModelAdd*() functions. These objects will be released automatically when the model is released. Example code:

// Create the model object
SUModelCreate(&model);
// Create a layer
SULayerCreate(&layer);
SUModelAddLayers(model, 1, &layer);
// Now release the model, which automatically releases the layer

Attach the object directly to another object

In this case, the created object is then owned by an existing object. For instance, a loop input can be added to a face as an inner loop. A material or layer can be added to any drawing element. These objects will be released automatically when the model is released.

// Assume you already have a model with a face in it
// Get the model's entities collection
SUModelGetEntities(model, &entities);
size_t count;
SUEntitiesGetNumFaces(entities, &count);
// Just get one face
SUEntitiesGetFaces(entities, 1, &face, &count);
// Create a material from a texture from a file
SUMaterialCreate(&material);
SUTextureCreateFromFile(&texture, "c:\\texture.jpg", 1.0, 1.0);
SUMaterialSetTexture(material, texture);
// Add the material to the face
SUFaceSetFrontMaterial(face, material);
// Now release the model, which automatically releases the
// face, the material, and the texture

Release the object manually

This is done by calling the corresponding SU*Release() function. This is not the typical use case for an object, except for the model itself as well as SUStringRef objects. However, it is possible to create and release many different types of objects explicitly. This is not advised however, because in most cases an active model is necessary for a function to operate properly.

SUPoint3D point1 = {0.0, 0.0, 0.0};
SUPoint3D point2 = {10.0, 20.0, 30.0};
SUEdgeCreate(&edge, &point1, &point2);
// Now release the edge explicitly

Transient Objects

A transient object is one that is not actually added to the model, but helps in the process. They are always explicitly created, are then used in some operation with the active model, and then are explicitly released. Examples of transient objects are: SUGeometryInputRef, SULoopInputRef, SUMeshHelperRef and SUUVHelperRef.

Exceptions to the general case rules

SUComponentInstanceRef - Component instances are actually created from an existing component definition using SUComponentDefinitionCreateInstance(). Though it can be released using SUComponentInstanceRelease(), the common pattern is to add the component instance to an entities collection using SUEntitiesAddInstance().

SUGeometryInputRef - Geometry input is a special type designed specifically allow you to input a large amount of geometry data to the model. The lifecycle of a geometry input object is that it is created, has vertex and loop data added to it, is added to an entities collection (using SUEntitiesFill()), and then is explicitly destroyed.

SUImageRef - An image can be created from a file using SUImageCreateFromFile(), however there is no corresponding release function. An image must be added to the entities collection of a model, component definition, or group. When the parent object is released, the image will be released automatically.

SUMeshHelperRef - A mesh helper is never added to another object, so it must always be explicitly released.

SUModelRef - Since a model is a top-level object, it must always be explicitly released.

SUStringRef - A string object is always created with one of the SUStringCreate*() functions. It is used to retrieve string data, like a name or a description, from an existing object (e.g., SUComponentInstanceGetName()). It must always be released using SUStringRelease() or you will leak memory. There is no memory management concern with the API regarding string data passed to an object (e.g., SUComponentInstanceSetName()), because a const char * is passed, not a SUStringRef.