Is there a way to access the SketchUp SDK from a C# .net project with out needing to learn C or C++?
Yes, with pinvoke.
See this link for more information on the subject:
I’ll have to play around and see if I can figure it out.
If anyone would happen to have some sample code I would be forever grateful.
For example how would I run the Quick start read file example from C#?
Or would it be easier to learn C++
#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;
SUResult res = SUModelCreateFromFile(&model, "model.skp");
// 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);
// 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;
}
First you’d have to wrap every function from the C SDK you intend to use in C#. Like this (real wrapper is 7k lines of code):
using System;
namespace YourNamespace
{
public class API
{
private const string LIB = "./lib/SketchUpAPI"; # this is a dll on windows or a dylib on OSx
[System.Runtime.InteropServices.DllImport(LIB, EntryPoint = "SUInitialize")]
public static extern void SUInitialize();
[System.Runtime.InteropServices.DllImport(LIB, EntryPoint = "SUTerminate")]
public static extern void SUTerminate();
[System.Runtime.InteropServices.DllImport(LIB, EntryPoint = "SUModelCreateFromFile")]
public static extern SUResult SUModelCreateFromFile(ref System.IntPtr model, [System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string file_path);
}
}
Once all your functions are wrapped you can call them:
API.SUInitialize();
var modelPtr = IntPtr.Zero;
var modelFilePath = "somewhere...";
API.SUModelCreateFromFile(ref modelPtr, modelFilePath);
# next is up to you...
API.SUTerminate();
Great thanks for posting that. Does a C# wrapper already exist somewhere for the C SDK?
Here is one … (author pushed SU2018 support only 18 days ago, so it is active.)
And for at least 4 years there has been a thread on SketchUcation pointing at a tutorial …
https://sketchucation.com/forums/viewtopic.php?f=180&t=55677
the tutorial …
https://bitbucket.org/icehuli/sucsexttutorial/wiki/Home
recently updated for SU2018.
Please forgive me for waking up this old topic, but I happen to be working on just such a wrapper lately and would be glad to have others involved.
Regarding this bit of code:
I think the best attribute for passing a string to the C API might be LPUTF8Str
, as this is the form the documentation says functions taking strings as input expect. For a lot of us, it won’t make any difference, as strings encoded in ASCII match their own UTF-8 encodings. But it doesn’t work the other way. That is, telling the marhsaller to convert a C# unicode string to LPStr
encoding might lose characters that are ouside the ASCII subset. (This means you can leave the MarshalAs
attribute out entirely, if you know your strings can always be represented correctly in the ASCII subset, but better to leave it in.)
Also, the In
attribute is optional. The marshaller does a pretty good job of inferring that kind of thing from our uses of ref
and out
.
Here’s a variation on kengey’s wrapper:
using System;
using System.Runtime.InteropServices;
namespace YourNamespace
{
public static class API
{
const string LIB = "SketchUpAPI";
[DllImport(LIB, EntryPoint = "SUInitialize")]
public static extern void SUInitialize();
[DllImport(LIB, EntryPoint = "SUTerminate")]
public static extern void SUTerminate();
[DllImport(LIB, EntryPoint = "SUModelCreateFromFile")]
public static extern SUResult SUModelCreateFromFile(
ref IntPtr model,
[MarshalAs(UnmanagedType.LPUTF8Str)]
string file_path);
}
}
Note that API
can be a static class,and that the Attribute
suffix of an attribute name is also optional.
I’d be very curious to know interested folks’ thoughts on these versions, and whether anyone sees any other issues in either of them.
Yes, it could have been less complicated.
Over the years I have wrapped the sdk more than once in C#, but I never really got to using it in production. In the end I always went for native.
It certainly can get tedious, wrapper after wrapper. I programmed in C for years, avoiding managed languages because they seemed slow and burdened with safety nets and training wheels that “real” programmers didn’t need. Today, I am completely on board with C#. In those rare (but not unheard of) cases where you need it, unsafe code provides the few things left in C I might miss. And all the tricks and magic the compiler writers and CPU designers have developed seem to have made any remaining performance issues almost vanish.
I worked in Java for a while, but its approach to calling native functions is a mess. You have no choice but to write original code in the native language, which not every programmer is even going to know. C# lets you write your wrappers entirely in C#. You do need to know about about memory layout and so on, but that’s a far cry from having to learn C.
So, my objective is to create a wrapper that is all C#. The other efforts I’ve seen use C++. That’s fine, but it means potential contributors who only know C# can’t help you. Now, as you clearly know, wrapping the entire C API is a big effort. I wanted something that would, at first, let me create models that I can import into Unity. Unity relies solely on C# as its programming language, so this seemed like the natural choice. So far, I’ve wrapped everything I need to create faces, components, groups, instances, and map them with materials. I can read and write those parts of a SketchUp file. Just to get that far, I’ve had to wrap 130 functions/structures.
To avoid having to deal with a lot of the nitty-gritty (counting vertex numbers, etc.) while creating models, I’ve written a companion library that lets me read a SketchUp model, then operate on it using a simplified document model that supports the features one needs for Unity models, then write it out to another SketchUp file for import into Unity. Basically, it is (yet another) import/export tool, but to and from a very simple document model.
If anyone reading this is interested in seeing what I’ve got, let me know! I’d be delighted to have others involved in it.
Cheers!
I looked at it, and so far what you show (in this repo) is not an API. You have a C# binding for the SketchUp C API. It (currently) still requires doing and accessing things in the clunky C way that some of us hate.
This is what I’d really be interested in, and true OOP API.
C# is a object oriented language that is C-like ( ie, C.O.O.L ) and us OOP geeks love Ruby (or Python) and like JavaScript, but wished it was compilable into executable or dynamic library files.
We’ve gotten spoiled with the weakly typed references that don’t need to be declared, and can point at any type object at any time or be changed to point at differently typed objects at any time during runtime.
But I’m sure most long time coders had to use strongly typed languages in the past (if not just in college,) and we’d likely accept the limitation if it means we can truly compile an app or extension.
But IMO, the object model for a publicly usable API needs to mirror the object model class structure of the Ruby API, (which I’m told mirrors the internal C++ object module as close as it could.)
If it diverges too much from this, those of us who’ve used it for many years (~10 in my case) will not adopt it (or adapt to it if they do,) all that that quickly.
There are also some issues to consider if it is to be an open source community project (be it binding, library or API … whatever the project goal will be.)
Namespace and licensing
-
You’ve wrapped it your proprietary company namespace.
-
You’ve declared copyright on it.
-
You’ve not attached any licensee or terms of use.
-
There are specific and general clauses in the Trimble API Terms of Service that apply to using their API and wrapping it. Those need to be considered, especially:
a. Section 2: Your End Users. (The API Terms need to be included.)
b. Section 3: Ownership.
c. Section 4: prohibition 1.
d. Section 6: Attribution.
e. Section 9: Liability (Disclaimers & Limitations need to be stated.)
Maintenance
-
Every single C API function is wrapped in a separate
.cs
file.
It is not just tedious to browse through. It may be likely that namespace names will change. I’d not wish to do this for every file manually. (Notepad++ can search and replace across files following a project folder structure and filtering for certain filetypes, like as.cs
files. I’d think VS should also have this ability.)
But for those familiar with the SketchUp API and it’s files, I’d (think) we’d prefer to be able to use it’s file naming structure for any binding or API wrapping. I’d want to open the"bindings/model/model.cs"
file and see the C# binding wrappers for ALL of theSUModelRef
object.
SketchUp C API: File List -
There is also work being done on the ability to use the C API on a “live” model. (Currently it is only safe to do readonly C API calls on a “live” model loaded into the SketchUp application proper.) There are 2 different libraries that need to be loaded (linked to) depending upon if the use is external or internal to the SketchUp application. (There are also a few functions that are only exported by the application itself.)
So anyway, it would be good if there was a way to decide which when it comes to specifying the API import library. -
Examples - It seems weird that examples for other people are wrapped in the same namespace as the API.
I’d think other coders will have their own namespace(s) and I’d hope that they would “import” the API with a “using” statement. Yes / No? If so examples should reflect actual use (and possibly serve as a template that coders can change the namespace identifiers to suit.using SketchUp.API namespace SomeCompany.SomeCertainPlugin { /// Code the uses the SketchUp API }
A few years ago I started working on a “real” c# api that was OO. So there was a Model class that had properties and functions, just like the ruby api has. I never worked on it profoundly because… well… other work had to be done.
Let me try to setup a github repo during the day, and if I don’t, please help me remember doing so.
Or @thomthom, maybe a repo could be setup on sketchup’s github?
I have a legal question about this. Since the wrapper needs the sdk binaries I was wondering if it is allowed to make these binaries part of the public repo?
Since the binaries are currently behind a login-wall - lets hold off on this for a bit.
We have an old copy of your wrapper and a Trimble wrapper in a private repo. We’ve not had time to work on it.
I’ve yet to have a look at Steven’s approach to this.
But there clearly is an interest and need for this.
Tommy started a C++ wrapper which has made progress:
Being maintained by the community it probably would work well for a community driven C# wrapper as well. But we have a few different solutions started.
Maybe we can do a breakout session at DevCamp in Leeds?
Personally I also have a C++ wrapper on top of the Ruby API that would be nice to open source. Maybe we can plan some time for Q4 this year for us (SketchUp) to aid in getting these wrappers out there.
Sounds good. Let’s reopen this discussion in a few weeks in Leeds.
Wow! Thanks for the detailed review, Dan.
Correct. It’s a wrapper. As a basic building block, I want to have as many C API functions wrapped as possible (ideally, all of them, though that’s a lot of work, and many are unnecessary for Unity developers). By starting with a transliteral implementation, nothing gets left out. After that, all further work can be done in C#, without having to worry about anything specific to C or even P/Invoke.
I see your point. I’m not (yet) familiar with the Ruby API. My design is driven by what a Unity gamedev would need. It does mimic the SketchUp document model, but it’s not married to it. I’ve got it close to ready for you to look at. Will probably be able to open it up this week.
Yes, as per “Elements of C# Style” R.3.11. I’m open to suggestions for other conventions, though.
Not explicitly. It’s actually pretty hard not to have copyrights under the Berne Convention, though you can transfer/sell them. Of course, Trimble has copyrights to its own material. I’d be grateful for your recommendations on this too.
Will do that before making it public. Would like to have Trimble’s okay on my choice and on making the project public overall.
That TOS appears directed at using an online API (consider “monitoring,” for example), but it is the one they link to from the C API documentation, so I take it as applicable. I believe I am (or will be) in compliance with its terms, but would ask for Trimble’s review/blessing.
Correct. They are named one-for-one for the functions they wrap, so finding any particular one would be easy. Since, with very few exceptions, they are transliteral, there would be little reason for anyone using them to want to see the source. But each function is easy to find because the names match. It wouldn’t be a big deal to gather the up into groups that match what’s in the various .h files in the C API, though. If there’s a call for that, I’d be happy to do it.
Agreed.
They actually are in different namespaces, but there’s no using
statement because the projects are in the same solution. You’re right, though. The examples should be as much like end-user code as they can be. I’ll break them out into a wholly isolated solution.
EDIT: You’re right! I’ll change it. And thanks for helping me learn something I didn’t know about C# namespaces.
That is absolutely awesome feedback, Dan, and fast, too. Many thanks!
Stevens
I wondered about that too. It appears that a number of public github repos already do this:
Because the TOS appears written with a Web API in mind, it’s kind of vague about this. The Developer Center Guidelines do address it, in a general way:
But, no need to play cute on a clear question. We should simply ask Trimble for permission and see what they say or what conditions they want to impose.
I’m afraid I won’t be in Leeds (I’m in Virginia, USA). But I would like to keep working on this. What do you all recommend? (Kenny, I know you haven’t seen my repo yet, but it is essentially the same, wrapper-by-wrapper, as the C# snippets you and I already posted here. Shortly, I’ll have a higher-level API to post as well, which I’d be glad to have you inspect along with Dan and Thom.)
"/CsharpSketchUpAPI/blob/master/CsharpSketchUpAPI/Properties/AssemblyInfo.cs"
… looked explicit to me … ie:
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CsharpSketchUpAPI")]
[assembly: AssemblyDescription("A C# wrapper for the SketchUp C API")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Ex Lumina Corporation")]
[assembly: AssemblyProduct("CsharpSketchUpAPI")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
And I believe you can make an explicit statement of no copyright, releasing to the public domain.
You can also have open source licenses (MIT, etc.) that has copyrights of each successive contributor and the license forbids the removal of these copyright statements.
It is also included within the download archive of the C API’s SDK. It is also linked from the Ruby API documentation pages.
There is (I think) an additional legal agreement document for registered developers (which applies in addition to the publicly posted terms.)
I think I’ve been through this question before with Thomas in a private thread.
We have this “informal” statement …
The C SDK “Main Page” specifically says …
The C API library for Windows is built using Microsoft Visual Studio 2015 SP1 (v140). It includes only 64-bit binaries. Building and releasing an application using the SketchUp C API for Windows requires including
SketchUpAPI.dll
andSketchUpCommonPreferences.dll
, which can be found in the SketchUp C SDK for Windows. Also, the following C runtime DLLs must be included:msvcp140.dll
andmsvcr140.dll
. Alternatively the Microsoft Visual C++ 2015 SP1 Redistributable Packages can be used … (gives MS download link.)
But not a good legalese statement of permission to distribute.