Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to build Open3D to be able to wrap the DLL for a .NET project? #7062

Open
2 of 3 tasks
reiseder opened this issue Nov 19, 2024 · 6 comments
Open
2 of 3 tasks

How to build Open3D to be able to wrap the DLL for a .NET project? #7062

reiseder opened this issue Nov 19, 2024 · 6 comments
Labels

Comments

@reiseder
Copy link

reiseder commented Nov 19, 2024

Checklist

My Question

I'm trying to compile Open3D to get a DLL which I can use in C++ project which exports methods that I can use in a .NET C# project via P/Invoke.

I have tried hints from #2889 and #5608, or whatever I could find on StackOverflow. Information is sparse.

I managed to build a DLL that I can use in a C++ console application that I created in Visual Studio but not in a project that is compiled to a DLL containing __declspec(dllexport).

As soon as I include Open3D.h my build fails with errors from various Open3D header files. I only have .NET/C# background so I don't know why it's even trying to build these files.

I'm only using the Windows runtime and I have tried to compile main and 0.18.0. The 0.18.0 build fails and/or the INSTALL target doesn't work as expected.

Do you have any information on this?

@reiseder
Copy link
Author

When I try to build the main branch with STATIC_WINDOWS_RUNTIME=ON it fails with the following error:

image

@jordanlui
Copy link

What errors are you having? Please post text of your errors, instead of screenshots.

I've succeeded in building Open3D static and DLL libraries from source, but I'm having troubles integrating it into my C++ projects.

From what I can tell, part of my issues are dependency clashes. Open3D packs some older versions of common dependencies (Eigen, fmt), and this can clash when your project relies different versions of these same libraries.

I tried to integrate the static libraries instead, in an attempt to isolate dependencies and remedy this problem. However, Open3D includes several of their external dependencies in their .h files, so I'm unable to fully isolate their dependencies.

With a quick find and grep, I see that their public headers include the following external dependencies, which mean that your solution needs to include:

  • Eigen
  • GL
  • GLFW
  • filament
  • fmt
  • imgui
  • ipp
  • nanoflann
  • tbb
  • vtk

@reiseder
Copy link
Author

reiseder commented Dec 5, 2024

I managed to get it to work in a Microsoft Visual C++/CLI project.

Now I can use Open3D in a native C++ class and wrap it in CLR C++ class for my C# project.

I will add my project settings in case someone needs them. Maybe someone wants to add some documentation to the project?

  1. The Open3D include and the 3rd party include/open3d/3rdparty directories need to be included

image

  1. The Open3D.lib needs to be added to the linker dependencies

image

  1. The Force File Output linker setting must be set to /FORCE:MULTIPLE (This was the crucial setting)

image


My problem was that I couldn't use the binaries from the releases (v0.18.0 or v0.17.0) directly. Adding them to a C++/CLI project resulted in build errors in Visual Studio, although they worked just fine in a C++ console application.

1>MyNativeClass.obj : error LNK2028: unresolved token (0A001CE9) "char __cdecl fmt::v6::internal::thousands_sep_impl<char>(class fmt::v6::internal::locale_ref)" (??$thousands_sep_impl@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z) referenced in function "public: unsigned __int64 __cdecl fmt::v6::internal::basic_writer<class fmt::v6::internal::buffer_range<char> >::padded_int_writer<struct fmt::v6::internal::basic_writer<class fmt::v6::internal::buffer_range<char> >::int_writer<int,struct fmt::v6::basic_format_specs<char> >::num_writer>::size(void)const " (?size@?$padded_int_writer@Unum_writer@?$int_writer@HU?$basic_format_specs@D@v6@fmt@@@?$basic_writer@V?$buffer_range@D@internal@v6@fmt@@@internal@v6@fmt@@@?$basic_writer@V?$buffer_range@D@internal@v6@fmt@@@internal@v6@fmt@@$$FQEBA_KXZ)
1>ClassLibrary1.obj : error LNK2028: unresolved token (0A001CED) "char __cdecl fmt::v6::internal::thousands_sep_impl<char>(class fmt::v6::internal::locale_ref)" (??$thousands_sep_impl@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z) referenced in function "char __cdecl fmt::v6::internal::thousands_sep<char>(class fmt::v6::internal::locale_ref)" (??$thousands_sep@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z)
1>MyNativeClass.obj : error LNK2020: unresolved token (0A001CEA) "public: static char const * const fmt::v6::internal::basic_data<void>::hex_digits" (?hex_digits@?$basic_data@X@internal@v6@fmt@@2QBDB)
1>ClassLibrary1.obj : error LNK2020: unresolved token (0A001CEE) "public: static char const * const fmt::v6::internal::basic_data<void>::hex_digits" (?hex_digits@?$basic_data@X@internal@v6@fmt@@2QBDB)
1>MyNativeClass.obj : error LNK2028: unresolved token (0A001CEB) "char __cdecl fmt::v6::internal::decimal_point_impl<char>(class fmt::v6::internal::locale_ref)" (??$decimal_point_impl@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z) referenced in function "char __cdecl fmt::v6::internal::decimal_point<char>(class fmt::v6::internal::locale_ref)" (??$decimal_point@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z)
1>ClassLibrary1.obj : error LNK2028: unresolved token (0A001CEF) "char __cdecl fmt::v6::internal::decimal_point_impl<char>(class fmt::v6::internal::locale_ref)" (??$decimal_point_impl@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z) referenced in function "char __cdecl fmt::v6::internal::decimal_point<char>(class fmt::v6::internal::locale_ref)" (??$decimal_point@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z)
1>MyNativeClass.obj : error LNK2020: unresolved token (0A001E06) "public: static char const * const fmt::v6::internal::basic_data<void>::digits" (?digits@?$basic_data@X@internal@v6@fmt@@2QBDB)
1>ClassLibrary1.obj : error LNK2020: unresolved token (0A001E0E) "public: static char const * const fmt::v6::internal::basic_data<void>::digits" (?digits@?$basic_data@X@internal@v6@fmt@@2QBDB)
1>ClassLibrary1.obj : error LNK2001: unresolved external symbol "public: static char const * const fmt::v6::internal::basic_data<void>::digits" (?digits@?$basic_data@X@internal@v6@fmt@@2QBDB)
1>MyNativeClass.obj : error LNK2001: unresolved external symbol "public: static char const * const fmt::v6::internal::basic_data<void>::digits" (?digits@?$basic_data@X@internal@v6@fmt@@2QBDB)
1>ClassLibrary1.obj : error LNK2001: unresolved external symbol "public: static char const * const fmt::v6::internal::basic_data<void>::hex_digits" (?hex_digits@?$basic_data@X@internal@v6@fmt@@2QBDB)
1>MyNativeClass.obj : error LNK2001: unresolved external symbol "public: static char const * const fmt::v6::internal::basic_data<void>::hex_digits" (?hex_digits@?$basic_data@X@internal@v6@fmt@@2QBDB)
1>ClassLibrary1.obj : error LNK2019: unresolved external symbol "char __cdecl fmt::v6::internal::thousands_sep_impl<char>(class fmt::v6::internal::locale_ref)" (??$thousands_sep_impl@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z) referenced in function "char __cdecl fmt::v6::internal::thousands_sep<char>(class fmt::v6::internal::locale_ref)" (??$thousands_sep@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z)
1>MyNativeClass.obj : error LNK2001: unresolved external symbol "char __cdecl fmt::v6::internal::thousands_sep_impl<char>(class fmt::v6::internal::locale_ref)" (??$thousands_sep_impl@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z)
1>ClassLibrary1.obj : error LNK2019: unresolved external symbol "char __cdecl fmt::v6::internal::decimal_point_impl<char>(class fmt::v6::internal::locale_ref)" (??$decimal_point_impl@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z) referenced in function "char __cdecl fmt::v6::internal::decimal_point<char>(class fmt::v6::internal::locale_ref)" (??$decimal_point@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z)
1>MyNativeClass.obj : error LNK2001: unresolved external symbol "char __cdecl fmt::v6::internal::decimal_point_impl<char>(class fmt::v6::internal::locale_ref)" (??$decimal_point_impl@D@internal@v6@fmt@@$$FYADVlocale_ref@012@@Z)

So I tried to build and install them myself. Which is actually a good thing because now I can change some build options and exclude the parts I don't need.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7b047cd0b..a9e9bd57d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,11 +34,11 @@ endif()
 include(CMakeDependentOption)
 
 # Open3D build options
-option(BUILD_SHARED_LIBS          "Build shared libraries"                   OFF)
-option(BUILD_EXAMPLES             "Build Open3D examples programs"           ON )
+option(BUILD_SHARED_LIBS          "Build shared libraries"                   ON )
+option(BUILD_EXAMPLES             "Build Open3D examples programs"           OFF)
 option(BUILD_UNIT_TESTS           "Build Open3D unit tests"                  OFF)
 option(BUILD_BENCHMARKS           "Build the micro benchmarks"               OFF)
-option(BUILD_PYTHON_MODULE        "Build the python module"                  ON )
+option(BUILD_PYTHON_MODULE        "Build the python module"                  OFF)
 option(BUILD_CUDA_MODULE          "Build the CUDA module"                    OFF)
 option(BUILD_WITH_CUDA_STATIC     "Build with static CUDA libraries"         ON )
 option(BUILD_COMMON_CUDA_ARCHS    "Build for common CUDA GPUs (for release)" OFF)
@@ -53,7 +53,7 @@ else()
     option(BUILD_ISPC_MODULE      "Build the ISPC module"                    OFF)
 endif()
 option(BUILD_COMMON_ISPC_ISAS     "Build for common ISPC ISAs (for release)" OFF)
-option(BUILD_GUI                  "Builds new GUI"                           ON )
+option(BUILD_GUI                  "Builds new GUI"                           OFF)
 option(WITH_OPENMP                "Use OpenMP multi-threading"               ON )
 option(WITH_IPP                "Use Intel Integrated Performance Primitives" ON )
 option(ENABLE_HEADLESS_RENDERING  "Use OSMesa for headless rendering"        OFF)

Building with my options worked just fine.

Installing however is when I ran into troubles...

When running cmake --build . --config Release --target INSTALL it tries to access a resource that doesn't exist or I don't have access to.

Since I was out of options I checked out main and used the latest commit. IT WORKED!

So, I will use this build until a new release comes out.

@reiseder
Copy link
Author

reiseder commented Dec 5, 2024

After analyzing the errors while writing the above comment I think I found the source of the error I encountered.

I checked out the v0.18.0 tag and in the files mkl_include\src\ext_mkl_include-stamp\download-ext_mkl_include.cmake and mkl_include\src\ext_mkl_include-stamp\ext_mkl_include-urlinfo.txt there is a W at the end of the first url.

C:\open3d\src\build\mkl_include\src\ext_mkl_include-stamp\download-ext_mkl_include.cmake (2 hits)
	Line  78: if("https://github.com/isl-org/Open3D/releases/download/v0.12.0/mkl-include-2020.1-intel_216-win-64.tar.bz2W;https://anaconda.org/intel/mkl-include/2020.1/download/win-64/mkl-include-2020.1-intel_216.tar.bz2" STREQUAL "")
	Line 118:   foreach(url https://github.com/isl-org/Open3D/releases/download/v0.12.0/mkl-include-2020.1-intel_216-win-64.tar.bz2W;https://anaconda.org/intel/mkl-include/2020.1/download/win-64/mkl-include-2020.1-intel_216.tar.bz2)
  C:\open3d\src\build\mkl_include\src\ext_mkl_include-stamp\ext_mkl_include-urlinfo.txt (1 hit)
	Line  9: url(s)=https://github.com/isl-org/Open3D/releases/download/v0.12.0/mkl-include-2020.1-intel_216-win-64.tar.bz2W;https://anaconda.org/intel/mkl-include/2020.1/download/win-64/mkl-include-2020.1-intel_216.tar.bz2

@reiseder
Copy link
Author

reiseder commented Dec 5, 2024

After fixing the files from #7062 (comment) I managed to build and install v0.18.0. I still can't use it in a C++/CLI project though.

@reiseder
Copy link
Author

I discovered that #define FMT_HEADER_ONLY is needed from this StackOverflow questions,

Now I can work with the 0.18.0 release.

Another thing is that I somehow need a DEBUG build of the Open3D.dll to make it work if I run my application with the Visual Studio Debugger.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants