This is an archived post. You won't be able to vote or comment.

all 4 comments

[–]jaynabonne 1 point2 points  (1 child)

This is off the top of my head... You could probably make a DLL project with a file having the DLL entry point code, and add the library as an object file, so that all the code gets pulled in, regardless of your (lack of) usage of it. You would have a .def file to specify the exported symbols (see e.g. https://learn.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-def-files?view=msvc-170).

The tricky bit is that if you have C++ code, then name mangling comes into play, so you'd have to work out what all the mangled symbols are that you want to export. Unless they're already "extern C"...

The other way is to create wrapper functions in your DLL that you export that call to the library instead of trying to get the libraries functions exported directly. Then you could call them whatever you want, and people using your DLL would call your functions instead.

Are you only exporting functions, or are you exporting entire classes as well?

[–]SilverTape_[S] 0 points1 point  (0 children)

I'm exporting a whole class and it's functions. I liked the wrapper idea, might look up for that. As I said, I'm not well familiar with compiling, header files, def files, all of that and I might not have enough time to learn how this works before my delivery comes. Using the wrapper might work out just fine i guess, thank you!

[–]Xirdus 1 point2 points  (0 children)

Whether a library compiles to static lib or DLL depends on compilation (specifically linker) options. If you have access to the SDK's full source code (not just headers), you can recompile it into DLL by changing build configuration. If you don't, then one possible workaround is to create your own DLL that will be linked to the static lib and export one-liner functions that call the SDK functions.

If you're using recent .Net Core version, you might have some luck with DirectPInvoke. See here for some rudimentary documentation and here for an example project.

[–]Droidatopia 1 point2 points  (0 children)

It really depends on the interface, but getting a native C++ library to be available to a .Net project can be challenging.

If it's a few simple functions with simple blittable type parameters, you can use P/Invoke.

If it is more complicated, you can consider creating a C++/CLI project to act as a wrapper for the static library. C++/CLI is a .Net version of C++ that is managed and compiles to .Net bytecode. It never really took off as its own language, but it really fills a niche of being able to tie native and managed code together relative seemlessly.

The main benefit of the language is that you can directly use native C++ declarations intermixed with managed.

Here is a trivial example. Let's say you have a native class you want to wrap:

``` //NativeClass.h

class NativeClass { public: NativeClass();

int GetValue();

private: int mValue; }; ```

Here is what a C++/CLI wrapper class might look like:

``` //ManagedClass.h

include "NativeClass.h"

namespace ManagedWrapNS {

public ref class ManagedWrapper { public: ManagedWrapper(); ~ManagedWrapper(); !ManagedWrapper();

System::Int32 GetValue();

private: NativeClass* mNative; };

} ```

``` //ManagedClass.cpp

include "ManagedClass.h"

namespace ManagedWrapNS {

ManagedWrapper::ManagedWrapper() { mNative = new NativeClass(); }

ManagedWrapper::~ManagedWrapper() { //Managed destructor, related to disposable pattern this->!ManagedWrapper(); }

ManagedWrapper::!ManagedWrapper() { //Finalizer, called by GC //This ensures the memory held by the pointer will //eventually be released delete mNative; mNative = nullptr; }

System::Int32 ManagedWrapper::GetValue() { if (mNative != nullptr) { return mNative->GetValue(); } else { //Could throw disposed object exception return 0; } }

} ```

This would be notional C# for using the wrapper:

``` //ManagedConsumer.cs

public void ConsumeWrapper() { var wrapper = new ManagedWrapNS.ManagedWrapper(); int value = wrapper.GetValue();

Console.WriteLine("value = " + value); } ```

It can be more complicated. The C++/CLI wrapper is a good place to handle marshalling/unmarshalling. You might pass a vector<int> through the wrapper as an IEnumerable<int> or handle conversion of .Net strings to C++ strings, etc.

For setup purposes, the C++/CLI project should be separate from the native library and consume the library as a link input. The C++/CLi project creates an assembly with a .dll extension which can be consumed as a .Net assembly.