1

I am designing some software that will be delivered to a customer with some limited areas that they can customize using the same platform and compiler (Windows 10, Visual Studio 2017). My goal is to allow them to inherit from a class and generate data from their own proprietary source and pass it to the main system.

I would like the code we deliver---except for the customizable part---to be closed source and unavailable to the customer. I was originally planning on delivering a set of .lib files and allowing them to use these libraries. I'm concerned about mixing debug and release code, though, as if I deliver debug files perhaps my source code and implementation will be available to them but it I deliver only release mode .lib files then perhaps they won't be able to debug without issues.

On the other hand, if I deliver DLL files perhaps I will have to spend a bit more time on interfaces and I worry about them allocating memory for the data and me having to free it (see here, for example).

For Windows and Visual Studio 2017, is there a standard way to implement this type of arrangement where the customer can implement added functionality while keeping certain proprietary code hidden?

A few options are release .lib/dll only or attempting to configure a debug build that contains no debug information.

12
  • 2
    @RobertHarvey My assumption was that they would have access to the headers only, not the cpp files
    – Steve
    Nov 20, 2017 at 23:08
  • 1
    It should be easy enough to test. Make a small library with a few classes with a few functions each, then try to compile a new app that uses the library. Nov 21, 2017 at 3:46
  • 2
    @RobertHarvey: you are both correct, C++ still lacks of an ABI standard, which means there are restrictions when linking against code of another vendor: the vendor needs to provide the binaries compiled with a compatible compiler (version), compatible standard libs and compatible compiler flags. So its possible, but not always practical.
    – Doc Brown
    Nov 21, 2017 at 6:34
  • 1
    It's not everyday that I am given a reason to be thankful for using Java.
    – Neil
    Nov 21, 2017 at 14:11
  • 1
    Because of Link-Time Code Generation (LTCG), you are already giving away lots of information anyway when you let someone else link to your code, as opposed to using your code via a DLL API.
    – rwong
    Nov 28, 2017 at 20:26

1 Answer 1

1

In my opinion you should just design a proper API for your clients to call while they compile plugins in the form of a dylib which gets loaded and invoked by your application.

It does require spending more time in advance to design your API/SDK but you can use it yourself to build your application, basically bootstrapping and building your own software with the same API and SDK that your customers use to build plugins for it. You give your clients headers indicating the interfaces they can use (ex: tables of function pointers) and pass them a pointer to access these interfaces when their plugin is loaded and an entry point function exported by their plugin is invoked. Only header files for public interfaces are exposed to your clients. The rest remains hidden. Simplistic example:

#ifndef SDK_H
#define SDK_H

// Central interface for your software development kit.
struct Sdk
{
    // A function available for your customers to call in their plugins.
    void (*do_something)(int x);
};

#endif

// Inside the plugin code, compiled separately away from your
// application with no access to its source code, only the
// header files for the SDK.
#include <sdk.h>

// This exported function inside the plugin gets loaded and called
// by your application when it loads this plugin, passing it a pointer
// to the SDK interface required to invoke all the functionality
// publicly available for plugins to call.
EXPORT void my_plugin_function(struct Sdk* sdk)
{
    // Make your application do something from within this plugin.
    sdk->do_something(123);
}

On top of this I'd actually use a C API (though you can implement the C functions in C++). C is the most widely standardized language for APIs. If you use C, you can even call those C functions from a wide range of programming languages and allow your customers to, say, implement their plugins in C#. They might then create like a YourSoftware.Net library which allows your C API to be used in a way that is idiomatic to the .NET languages and framework just as people have done with, say, OpenGL. This isn't the case so much if you create a C++ API which is subject to more vendor issues which lack an ABI standard, name-mangling of exported symbols for function overloading which could be very compiler-specific and fugly to import at the very least, exceptions which can't be safely thrown across module boundaries, type capabilities like copy ctors and dtors which some languages won't know what to do with, etc.

Likewise you can build a static C++ library on top which wraps the C API and turns it into idiomatic C++ code (ex: translating error codes into exceptions, turning C resources which have to be freed manually into RAII-conforming C++ objects with destructors, function pointers into virtual functions, etc).

This does take time and thought, especially if it's your first time doing it, but it is the primary way that extensible plugin architectures are created, and the benefits of doing this properly, if it is actually needed, often outweigh the costs in the long run.

Another option is to embed a scripting language into your application, like Lua. Then your clients can write Lua code which calls functions in your application at runtime, and you can even have a scripting console directly inside of your software where your customers can type in code and run it on the fly without restarting the application. That also carries its share of advance work though that tends to be as costly or even more than designing a C SDK, but it does let you do some really cool things with your software at runtime and can actually aid a lot in testing its functions at runtime on the fly even if you prefer to write the majority of the code in C++.

I'm concerned about mixing debug and release code, though, as if I deliver debug files perhaps my source code and implementation will be available to them but it I deliver only release mode .lib files then perhaps they won't be able to debug without issues.

I think this is an impractical concern. If I'm writing plugins for Google Chrome, I'm not interested in debugging Google Chrome's codebase, only the code for my plugin. Most likely your customers won't be so interested in wading through the implementation details of your codebase just as you aren't interested in letting them see it. The usual way is to give the clients release binaries. They write plugins and can build debug versions of those and debug and trace through their own code extending your application's capabilities, but don't bother with debugging your code and tracing into the API calls.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.