SketchUp C API

- Main Page
- Related Pages
- Data Structures
- Files

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends 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.

All interactions with the SketchUp C API must be performed from the main thread to avoid unexpected behavior and application instability.

## Units

Sketchup uses inches for internal geometric values such as length, area and volume. This is also valid for values stored in .skp and .layout file formats. The internal tolerance for the equality of 3D points and vectors is `0.001`.

## 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 2022 (v143). 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++ 2022 Redistributable Packages can be used, which can be found here:

64-bit redistributable package

#### History

SketchUp 2020, 2021, 2022, and 2023.0 for Windows were built using Visual Studio 2019, and so plugins should be built with the Platform Toolset set to Visual Studio 2019 (v142). Using a different Platform Toolset will likely cause the plugin to fail to load and cause SketchUp to crash.

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

Starting with SketchUp 2022.0, universal binaries are supported. Universal binaries on macOS run natively on both Apple silicon and Intel-based Mac computers.

SketchUp 2022 was built with target SDK 10.14. 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 2021 was built with target SDK 10.13.

SketchUp 2020 was built with target SDK 10.12.

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:

- Third-party application adding support for reading and/or writing .skp files.
- SketchUp Importer/Exporter plugin.
- SketchUp extension reading/writing .skp files separate from the open model.

#### Windows

- Add `<SDK_PATH>\headers` to the include paths.
- Link against `<SDK_PATH>\binaries\sketchup\x64\SketchUpAPI.lib`

#### macOS

- Add `<SDK_PATH>` to framework search paths.
- Link against `SketchUpAPI.framework`

### Extension Usage (Live C API)

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

#### Windows

- Add `<SDK_PATH>\headers` to the include paths.
- Link against `<SDK_PATH>\binaries\sketchup\x64\sketchup.lib` (Do not link against `SketchUpAPI.lib`!)

#### macOS

- Add `<SDK_PATH>` to framework search paths.
- Set `/Application/SketchUp 2019/SketchUp.app/Contents/MacOS/SketchUp` as the bundle loader. (Do not link against `SketchUpAPI.framework`!)

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 <SketchUpAPI/slapi.h>
#include <SketchUpAPI/geometry.h>
#include <SketchUpAPI/initialize.h>
#include <SketchUpAPI/unicodestring.h>
#include <SketchUpAPI/model/model.h>
#include <SketchUpAPI/model/entities.h>
#include <SketchUpAPI/model/face.h>
#include <SketchUpAPI/model/edge.h>
#include <SketchUpAPI/model/vertex.h>
#include <vector>
int main() {
// Always initialize the API before using it
SUInitialize();
// Load the model from a file
SUModelRef model = SU_INVALID;
SUModelLoadStatus status;
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;
}
if (status == SUModelLoadStatus_Success_MoreRecent) {
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.
SUEntitiesRef entities = SU_INVALID;
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
SUStringRef name = SU_INVALID;
SUStringCreate(&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
SUStringRelease(&name);
delete []name_utf8;
// Must release the model or there will be memory leaks
SUModelRelease(&model);
// Always terminate the API when done using it
SUTerminate();
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 <SketchUpAPI/slapi.h>
#include <SketchUpAPI/geometry.h>
#include <SketchUpAPI/initialize.h>
#include <SketchUpAPI/model/model.h>
#include <SketchUpAPI/model/entities.h>
#include <SketchUpAPI/model/face.h>
#include <SketchUpAPI/model/edge.h>
#include <SketchUpAPI/model/vertex.h>
#include <vector>
int main() {
// Always initialize the API before using it
SUInitialize();
// Create an empty model
SUModelRef model = SU_INVALID;
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
SUEntitiesRef entities = SU_INVALID;
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
SUFaceRef face = SU_INVALID;
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
SUTerminate();
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:

- SUFaceRef
- SUEdgeRef
- SUCurveRef
- SUArcCurveRef
- SUGroupRef
- SUImageRef
- SUComponentInstanceRef

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
SUModelRef model = SU_INVALID;
SUModelCreate(&model);
// Get the model's entities collection
SUEntitiesRef entities = SU_INVALID;
SUModelGetEntities(model, &entities);
// Create an edge
SUEdgeRef edge = SU_INVALID;
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
SUModelRelease(&model);

### 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
SUModelRef model = SU_INVALID;
SUModelCreate(&model);
// Create a layer
SULayerRef layer = SU_INVALID;
SULayerCreate(&layer);
SUModelAddLayers(model, 1, &layer);
// Now release the model, which automatically releases the layer
SUModelRelease(&model);

### 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
SUEntitiesRef entities = SU_INVALID;
SUModelGetEntities(model, &entities);
size_t count;
SUEntitiesGetNumFaces(entities, &count);
SUFaceRef face = SU_INVALID;
// Just get one face
SUEntitiesGetFaces(entities, 1, &face, &count);
// Create a material from a texture from a file
SUMaterialRef material = SU_INVALID;
SUMaterialCreate(&material);
SUTextureRef texture = SU_INVALID;
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
SUModelRelease(&model);

### 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.

SUEdgeRef edge = SU_INVALID;
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
SUEdgeRelease(&edge);

### 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.