├── .clang-format ├── .editorconfig ├── .gitignore ├── .gitmodules ├── AUTHORS ├── CMakeLists.txt ├── CMakePresets.json ├── GDC2024.pdf ├── LICENSE ├── NuGet.config ├── README.md ├── build.sh ├── cmake ├── CSharpifyDefinitions.cmake ├── CSharpifyDotnet.cmake └── PatchFile.cmake ├── config.cmake.in ├── dotnet-deps ├── CMakeLists.txt ├── imports │ ├── android-arm64-mono.props │ ├── android-x64-mono.props │ ├── ios-arm64-mono.props │ ├── ios-arm64-nativeaot.props │ ├── linux-arm64-coreclr.props │ ├── linux-arm64-mono.props │ ├── linux-x64-coreclr.props │ ├── linux-x64-mono.props │ ├── linux_bionic-arm64-nativeaot.props │ ├── linux_bionic-x64-nativeaot.props │ ├── osx-arm64-coreclr.props │ ├── osx-arm64-mono.props │ ├── osx-arm64-nativeaot.props │ ├── osx-x64-coreclr.props │ ├── osx-x64-mono.props │ ├── osx-x64-nativeaot.props │ ├── plat-arch-runtime.props.template │ ├── win-x64-coreclr.props │ └── win-x64-mono.props ├── other-imports.props └── packages.csproj ├── dotnet-install.ps1 ├── managed ├── CMakeLists.txt ├── Directory.Build.props.in ├── Directory.Build.targets ├── main.cs ├── managed.csproj └── managed.sln ├── native ├── CMakeLists.txt ├── config.h.in ├── coreclr │ ├── bridge.h │ ├── coreclr.cpp │ ├── coreclr_win.cpp │ └── runtime.h ├── csharpify.sln ├── include │ ├── common.h │ ├── coreclrhost.h │ ├── imgui_bridge.h │ ├── main.h │ ├── managed_bridge.h │ ├── managed_exports.h │ └── utils.h ├── main.cpp ├── mono │ ├── bridge.h │ ├── mono.cpp │ └── runtime.h └── utils.cpp ├── pack.sh └── packages ├── .gitignore ├── DNNE.2.0.6.2.nupkg ├── ImGui.NET.1.90.1.1.nupkg └── SDL2-CS.2.0.30.nupkg /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: LLVM 4 | AccessModifierOffset: -4 5 | AlignConsecutiveAssignments: false 6 | AlignConsecutiveDeclarations: false 7 | AlignOperands: false 8 | AlignTrailingComments: true 9 | AllowShortBlocksOnASingleLine: false 10 | AllowShortFunctionsOnASingleLine: None 11 | AlwaysBreakTemplateDeclarations: Yes 12 | BraceWrapping: 13 | AfterCaseLabel: true 14 | AfterClass: true 15 | AfterControlStatement: false 16 | AfterEnum: true 17 | AfterFunction: true 18 | AfterNamespace: true 19 | AfterStruct: true 20 | AfterUnion: true 21 | AfterExternBlock: false 22 | BeforeCatch: true 23 | BeforeElse: true 24 | BeforeLambdaBody: true 25 | BeforeWhile: true 26 | SplitEmptyFunction: true 27 | SplitEmptyRecord: true 28 | SplitEmptyNamespace: true 29 | AfterObjCDeclaration: false 30 | IndentBraces: false 31 | BreakBeforeBraces: Custom 32 | BreakConstructorInitializers: AfterColon 33 | ColumnLimit: 120 34 | IncludeCategories: 35 | - Regex: ^<.* 36 | Priority: 1 37 | - Regex: ^".* 38 | Priority: 2 39 | - Regex: .* 40 | Priority: 3 41 | IncludeIsMainRegex: ([-_](test|unittest))?$ 42 | IndentWidth: 4 43 | InsertNewlineAtEOF: true 44 | MaxEmptyLinesToKeep: 2 45 | NamespaceIndentation: All 46 | SpacesInAngles: false 47 | TabWidth: 4 48 | UseTab: Always 49 | ... 50 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{c,c++,c++m,cc,ccm,cginc,compute,cp,cpp,cppm,cu,cuh,cxx,cxxm,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,mpp,mq4,mq5,mqh,mxx,tpp,usf,ush}] 4 | indent_style = tab 5 | indent_size = tab 6 | tab_width = 4 7 | charset = utf-8 8 | 9 | [*] 10 | # ReSharper properties 11 | resharper_cpp_indent_style = tab 12 | resharper_cpp_other_braces = end_of_line 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | 6 | # Icon must end with two \r 7 | Icon 8 | 9 | 10 | # Thumbnails 11 | ._* 12 | 13 | # Files that might appear in the root of a volume 14 | .DocumentRevisions-V100 15 | .fseventsd 16 | .Spotlight-V100 17 | .TemporaryItems 18 | .Trashes 19 | .VolumeIcon.icns 20 | .com.apple.timemachine.donotpresent 21 | 22 | # Directories potentially created on remote AFP share 23 | .AppleDB 24 | .AppleDesktop 25 | Network Trash Folder 26 | Temporary Items 27 | .apdisk 28 | 29 | 30 | *.swp 31 | *.*~ 32 | project.lock.json 33 | .DS_Store 34 | *.pyc 35 | nupkg/ 36 | 37 | # User-specific files 38 | *.suo 39 | *.ruser 40 | *.user 41 | *.userosscache 42 | *.sln.docstates 43 | *.userprefs 44 | 45 | # Build results 46 | [Dd]ebug/ 47 | [Dd]ebugPublic/ 48 | [Rr]elease/ 49 | [Rr]eleases/ 50 | x64/ 51 | x86/ 52 | build/ 53 | bld/ 54 | [Bb]in/ 55 | [Oo]bj/ 56 | [Oo]ut/ 57 | msbuild.log 58 | msbuild.err 59 | msbuild.wrn 60 | 61 | # Prerequisites 62 | *.d 63 | 64 | # Compiled Object files 65 | *.slo 66 | *.lo 67 | *.o 68 | *.obj 69 | 70 | # Precompiled Headers 71 | *.gch 72 | *.pch 73 | 74 | # Compiled Dynamic libraries 75 | *.so 76 | *.dylib 77 | *.dll 78 | *.bundle 79 | 80 | # Fortran module files 81 | *.mod 82 | *.smod 83 | 84 | # Compiled Static libraries 85 | *.lai 86 | *.la 87 | *.a 88 | *.lib 89 | 90 | # Executables 91 | *.exe 92 | *.out 93 | *.app 94 | 95 | # Build results 96 | [Dd]ebug/ 97 | [Dd]ebugPublic/ 98 | [Rr]elease/ 99 | [Rr]eleases/ 100 | x64/ 101 | x86/ 102 | [Ww][Ii][Nn]32/ 103 | [Aa][Rr][Mm]/ 104 | [Aa][Rr][Mm]64/ 105 | bld/ 106 | [Bb]in/ 107 | [Oo]bj/ 108 | [Ll]og/ 109 | [Ll]ogs/ 110 | 111 | ## IDES 112 | 113 | .vs/ 114 | .idea/ 115 | .vscode/ 116 | *.sln.iml 117 | .history/ 118 | .gradle/ 119 | JSON/ 120 | xcuserdata/ 121 | project.xcworkspace 122 | 123 | ## Ignore Visual Studio temporary files, build results, and 124 | ## files generated by popular Visual Studio add-ons. 125 | ## 126 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 127 | 128 | 129 | # Mono auto generated files 130 | mono_crash.* 131 | 132 | # Visual Studio 2017 auto generated files 133 | Generated\ Files/ 134 | 135 | # MSTest test Results 136 | [Tt]est[Rr]esult*/ 137 | [Bb]uild[Ll]og.* 138 | 139 | # NUnit 140 | *.VisualState.xml 141 | TestResult.xml 142 | nunit-*.xml 143 | 144 | # Build Results of an ATL Project 145 | [Dd]ebugPS/ 146 | [Rr]eleasePS/ 147 | dlldata.c 148 | 149 | # Benchmark Results 150 | BenchmarkDotNet.Artifacts/ 151 | 152 | # .NET Core 153 | project.lock.json 154 | project.fragment.lock.json 155 | artifacts/ 156 | 157 | # ASP.NET Scaffolding 158 | ScaffoldingReadMe.txt 159 | 160 | # StyleCop 161 | StyleCopReport.xml 162 | 163 | # Files built by Visual Studio 164 | *_i.c 165 | *_p.c 166 | *_h.h 167 | *.ilk 168 | *.meta 169 | *.obj 170 | *.iobj 171 | *.pch 172 | *.pdb 173 | *.ipdb 174 | *.pgc 175 | *.pgd 176 | *.rsp 177 | *.sbr 178 | *.tlb 179 | *.tli 180 | *.tlh 181 | *.tmp 182 | *.tmp_proj 183 | *_wpftmp.csproj 184 | *.log 185 | *.tlog 186 | *.vspscc 187 | *.vssscc 188 | .builds 189 | *.pidb 190 | *.svclog 191 | *.scc 192 | 193 | # Chutzpah Test files 194 | _Chutzpah* 195 | 196 | # Visual C++ cache files 197 | ipch/ 198 | *.aps 199 | *.ncb 200 | *.opendb 201 | *.opensdf 202 | *.sdf 203 | *.cachefile 204 | *.VC.db 205 | *.VC.VC.opendb 206 | 207 | # Visual Studio profiler 208 | *.psess 209 | *.vsp 210 | *.vspx 211 | *.sap 212 | 213 | # Visual Studio Trace Files 214 | *.e2e 215 | 216 | # TFS 2012 Local Workspace 217 | $tf/ 218 | 219 | # Guidance Automation Toolkit 220 | *.gpState 221 | 222 | # ReSharper is a .NET coding add-in 223 | _ReSharper*/ 224 | *.[Rr]e[Ss]harper 225 | 226 | # TeamCity is a build add-in 227 | _TeamCity* 228 | 229 | # DotCover is a Code Coverage Tool 230 | *.dotCover 231 | 232 | # AxoCover is a Code Coverage Tool 233 | .axoCover/* 234 | !.axoCover/settings.json 235 | 236 | # Coverlet is a free, cross platform Code Coverage Tool 237 | coverage*.json 238 | coverage*.xml 239 | coverage*.info 240 | 241 | # Visual Studio code coverage results 242 | *.coverage 243 | *.coveragexml 244 | 245 | # NCrunch 246 | _NCrunch_* 247 | .*crunch*.local.xml 248 | nCrunchTemp_* 249 | 250 | # MightyMoose 251 | *.mm.* 252 | AutoTest.Net/ 253 | 254 | # Web workbench (sass) 255 | .sass-cache/ 256 | 257 | # Installshield output folder 258 | [Ee]xpress/ 259 | 260 | # DocProject is a documentation generator add-in 261 | DocProject/buildhelp/ 262 | DocProject/Help/*.HxT 263 | DocProject/Help/*.HxC 264 | DocProject/Help/*.hhc 265 | DocProject/Help/*.hhk 266 | DocProject/Help/*.hhp 267 | DocProject/Help/Html2 268 | DocProject/Help/html 269 | 270 | # Click-Once directory 271 | publish/ 272 | 273 | # Publish Web Output 274 | *.[Pp]ublish.xml 275 | *.azurePubxml 276 | # Note: Comment the next line if you want to checkin your web deploy settings, 277 | # but database connection strings (with potential passwords) will be unencrypted 278 | *.pubxml 279 | *.publishproj 280 | 281 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 282 | # checkin your Azure Web App publish settings, but sensitive information contained 283 | # in these scripts will be unencrypted 284 | PublishScripts/ 285 | 286 | # NuGet Packages 287 | *.nupkg 288 | # NuGet Symbol Packages 289 | *.snupkg 290 | # The packages folder can be ignored because of Package Restore 291 | # Uncomment if necessary however generally it will be regenerated when needed 292 | #!**/[Pp]ackages/repositories.config 293 | # NuGet v3's project.json files produces more ignorable files 294 | *.nuget.props 295 | *.nuget.targets 296 | 297 | # Microsoft Azure Build Output 298 | csx/ 299 | *.build.csdef 300 | 301 | # Microsoft Azure Emulator 302 | ecf/ 303 | rcf/ 304 | 305 | # Windows Store app package directories and files 306 | AppPackages/ 307 | BundleArtifacts/ 308 | Package.StoreAssociation.xml 309 | _pkginfo.txt 310 | *.appx 311 | *.appxbundle 312 | *.appxupload 313 | 314 | # Visual Studio cache files 315 | # files ending in .cache can be ignored 316 | *.[Cc]ache 317 | # but keep track of directories ending in .cache 318 | !?*.[Cc]ache/ 319 | 320 | # Others 321 | ClientBin/ 322 | ~$* 323 | *~ 324 | *.dbmdl 325 | *.dbproj.schemaview 326 | *.jfm 327 | *.pfx 328 | *.publishsettings 329 | orleans.codegen.cs 330 | 331 | # Including strong name files can present a security risk 332 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 333 | #*.snk 334 | 335 | # Since there are multiple workflows, uncomment next line to ignore bower_components 336 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 337 | #bower_components/ 338 | 339 | # RIA/Silverlight projects 340 | Generated_Code/ 341 | 342 | # Backup & report files from converting an old project file 343 | # to a newer Visual Studio version. Backup files are not needed, 344 | # because we have git ;-) 345 | _UpgradeReport_Files/ 346 | Backup*/ 347 | UpgradeLog*.XML 348 | UpgradeLog*.htm 349 | ServiceFabricBackup/ 350 | *.rptproj.bak 351 | 352 | # SQL Server files 353 | *.mdf 354 | *.ldf 355 | *.ndf 356 | 357 | # Business Intelligence projects 358 | *.rdl.data 359 | *.bim.layout 360 | *.bim_*.settings 361 | *.rptproj.rsuser 362 | *- [Bb]ackup.rdl 363 | *- [Bb]ackup ([0-9]).rdl 364 | *- [Bb]ackup ([0-9][0-9]).rdl 365 | 366 | # Microsoft Fakes 367 | FakesAssemblies/ 368 | 369 | # GhostDoc plugin setting file 370 | *.GhostDoc.xml 371 | 372 | # Node.js Tools for Visual Studio 373 | .ntvs_analysis.dat 374 | node_modules/ 375 | 376 | # Visual Studio 6 build log 377 | *.plg 378 | 379 | # Visual Studio 6 workspace options file 380 | *.opt 381 | 382 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 383 | *.vbw 384 | 385 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 386 | *.vbp 387 | 388 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 389 | *.dsw 390 | *.dsp 391 | 392 | # Visual Studio 6 technical files 393 | *.ncb 394 | *.aps 395 | 396 | # Visual Studio LightSwitch build output 397 | **/*.HTMLClient/GeneratedArtifacts 398 | **/*.DesktopClient/GeneratedArtifacts 399 | **/*.DesktopClient/ModelManifest.xml 400 | **/*.Server/GeneratedArtifacts 401 | **/*.Server/ModelManifest.xml 402 | _Pvt_Extensions 403 | 404 | # Paket dependency manager 405 | .paket/paket.exe 406 | paket-files/ 407 | 408 | # FAKE - F# Make 409 | .fake/ 410 | 411 | # CodeRush personal settings 412 | .cr/personal 413 | 414 | # Python Tools for Visual Studio (PTVS) 415 | __pycache__/ 416 | *.pyc 417 | 418 | # Cake - Uncomment if you are using it 419 | # tools/** 420 | # !tools/packages.config 421 | 422 | # Tabs Studio 423 | *.tss 424 | 425 | # Telerik's JustMock configuration file 426 | *.jmconfig 427 | 428 | # BizTalk build output 429 | *.btp.cs 430 | *.btm.cs 431 | *.odx.cs 432 | *.xsd.cs 433 | 434 | # OpenCover UI analysis results 435 | OpenCover/ 436 | 437 | # Azure Stream Analytics local run output 438 | ASALocalRun/ 439 | 440 | # MSBuild Binary and Structured Log 441 | *.binlog 442 | 443 | # NVidia Nsight GPU debugger configuration file 444 | *.nvuser 445 | 446 | # MFractors (Xamarin productivity tool) working folder 447 | .mfractor/ 448 | 449 | # Local History for Visual Studio 450 | .localhistory/ 451 | 452 | # Visual Studio History (VSHistory) files 453 | .vshistory/ 454 | 455 | # BeatPulse healthcheck temp database 456 | healthchecksdb 457 | 458 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 459 | MigrationBackup/ 460 | 461 | # Ionide (cross platform F# VS Code tools) working folder 462 | .ionide/ 463 | 464 | # Fody - auto-generated XML schema 465 | FodyWeavers.xsd 466 | 467 | # VS Code files for those working on multiple tools 468 | !.vscode/settings.json 469 | !.vscode/tasks.json 470 | !.vscode/launch.json 471 | !.vscode/extensions.json 472 | *.code-workspace 473 | 474 | # Local History for Visual Studio Code 475 | .history/ 476 | 477 | # Windows Installer files from build outputs 478 | *.cab 479 | *.msi 480 | *.msix 481 | *.msm 482 | *.msp 483 | 484 | # Windows thumbnail cache files 485 | Thumbs.db 486 | Thumbs.db:encryptable 487 | ehthumbs.db 488 | ehthumbs_vista.db 489 | 490 | # Dump file 491 | *.stackdump 492 | 493 | # Folder config file 494 | [Dd]esktop.ini 495 | 496 | # Recycle Bin used on file shares 497 | $RECYCLE.BIN/ 498 | 499 | # Windows Installer files 500 | *.cab 501 | *.msi 502 | *.msix 503 | *.msm 504 | *.msp 505 | 506 | # Windows shortcuts 507 | *.lnk 508 | 509 | ## Dear ImGui artifacts 510 | imgui.ini 511 | 512 | Makefile.in 513 | aclocal.m4 514 | autom4te.cache/ 515 | config.guess 516 | config.sub 517 | configure 518 | install-sh 519 | missing 520 | src/Makefile.in 521 | compile 522 | depcomp 523 | stamp-h 524 | config.status 525 | .deps 526 | Makefile 527 | .stamp* 528 | src/net8.0 529 | .dirstamp 530 | .packages 531 | generated/ 532 | log 533 | .dotnet/ 534 | install/ 535 | managed/Directory.Build.props 536 | *.zip -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "imgui"] 2 | path = imgui 3 | url = git@github.com:ocornut/imgui.git 4 | [submodule "cimgui"] 5 | path = cimgui 6 | url = https://github.com/cimgui/cimgui 7 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Andreia Gaita -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.26) 2 | project(csharpify 3 | VERSION 1.1 4 | DESCRIPTION "Package and example of how to embed C# in C++ applications." 5 | ) 6 | 7 | if(POLICY CMP0091) 8 | cmake_policy(SET CMP0091 NEW) 9 | endif() 10 | 11 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 12 | include(CSharpifyDefinitions) 13 | include(CSharpifyDotnet) 14 | 15 | add_subdirectory(dotnet-deps) 16 | 17 | # Yes, this is included twice. It's on purpose, so it can finish setting up defined after the dotnet-deps restore is done. 18 | include(CSharpifyDotnet) 19 | 20 | set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "") 21 | if(NOT CMAKE_BUILD_TYPE) 22 | set(CMAKE_BUILD_TYPE "Debug") 23 | endif() 24 | 25 | message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") 26 | 27 | if(DOTNET_PLATFORM STREQUAL "osx") 28 | find_library(IOKIT IOKit) 29 | find_library(COCOA Cocoa) 30 | find_library(COREVIDEO CoreVideo) 31 | elseif(DOTNET_PLATFORM STREQUAL "win") 32 | 33 | # There is also the possibility of downloading pre-packaged source release instead of 34 | # grabbing the git tag. 35 | set(BUILD_SDL2 1) 36 | elseif(DOTNET_PLATFORM STREQUAL "linux") 37 | # We could consume an existing package, but we can also just build our own 38 | # and not require extra steps to make this work. 39 | set(BUILD_SDL2 1) 40 | endif() 41 | 42 | if(BUILD_SDL2) 43 | set(SDL2_DISABLE_SDL2MAIN 1) 44 | set(SDL_TEST 0) 45 | set(BUILD_SHARED_LIBS 0) 46 | set(SDL_VULKAN 1) 47 | set(SDL_DIRECTX 0) 48 | include(FetchContent) 49 | FetchContent_Declare( 50 | sdl2 51 | GIT_REPOSITORY https://github.com/libsdl-org/SDL 52 | GIT_TAG SDL2 53 | ) 54 | FetchContent_MakeAvailable(sdl2) 55 | 56 | elseif(DOTNET_PLATFORM STREQUAL "win") 57 | include(FetchContent) 58 | FetchContent_Declare( 59 | sdl2 60 | URL https://github.com/libsdl-org/SDL/releases/download/release-2.30.0/SDL2-devel-2.30.0-VC.zip 61 | URL_HASH MD5=179d5f19c62c16343a3bd606ea5b121a 62 | ) 63 | FetchContent_MakeAvailable(sdl2) 64 | 65 | list(APPEND CMAKE_PREFIX_PATH "${sdl2_SOURCE_DIR}") 66 | 67 | set(HAVE_SDL2_PACKAGE 1) 68 | else() 69 | set(HAVE_SDL2_PACKAGE 1) 70 | endif() 71 | 72 | if(HAVE_SDL2_PACKAGE) 73 | find_package(SDL2 REQUIRED) 74 | endif() 75 | 76 | if(DOTNET_PLATFORM STREQUAL "osx" OR DOTNET_PLATFORM STREQUAL "ios") 77 | set(USE_MOLTENVK 1) 78 | endif() 79 | 80 | if(USE_MOLTENVK) 81 | find_package(Vulkan REQUIRED COMPONENTS MoltenVK) 82 | else() 83 | find_package(Vulkan REQUIRED) 84 | set(Vulkan_MoltenVK_LIBRARY "") 85 | endif() 86 | 87 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 88 | message(STATUS "CMAKE_INSTALL_PREFIX is not set. Default value is '${CMAKE_INSTALL_PREFIX}', will set it to ${CMAKE_SOURCE_DIR}/install") 89 | set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install" CACHE PATH "Where the library will be installed to" FORCE) 90 | endif() 91 | 92 | file(MAKE_DIRECTORY packages) 93 | 94 | set(IMGUI_STATIC 0 CACHE BOOL "" FORCE) 95 | set(IMGUI_OBJECT 1 CACHE BOOL "" FORCE) 96 | 97 | add_subdirectory(managed) 98 | add_subdirectory(native) 99 | 100 | set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT csharpify) 101 | 102 | install(TARGETS csharpify_coreclr EXPORT csharpify_coreclr_export 103 | FILE_SET HEADERS DESTINATION include/csharpify/coreclr 104 | ) 105 | 106 | install(TARGETS csharpify_mono EXPORT csharpify_mono_export 107 | FILE_SET HEADERS DESTINATION include/csharpify/mono 108 | ) 109 | 110 | install(DIRECTORY ${csharpify_native_SOURCE_DIR}/coreclr/ DESTINATION include/csharpify/coreclr 111 | FILES_MATCHING PATTERN "*.cpp") 112 | 113 | install(DIRECTORY ${csharpify_native_SOURCE_DIR}/mono/ DESTINATION include/csharpify/mono 114 | FILES_MATCHING PATTERN "*.cpp") 115 | 116 | install(EXPORT csharpify_coreclr_export 117 | FILE CSharpifyCoreCLR.cmake 118 | DESTINATION lib/cmake/csharpify 119 | ) 120 | 121 | install(EXPORT csharpify_mono_export 122 | FILE CSharpifyMono.cmake 123 | DESTINATION lib/cmake/csharpify 124 | ) 125 | 126 | install(FILES 127 | cmake/CSharpifyDefinitions.cmake 128 | cmake/CSharpifyDotnet.cmake 129 | native/config.h.in 130 | DESTINATION lib/cmake/csharpify 131 | ) 132 | 133 | install(FILES 134 | LICENSE 135 | AUTHORS 136 | DESTINATION "./" 137 | ) 138 | 139 | install(DIRECTORY ${CMAKE_SOURCE_DIR}/dotnet-deps/ DESTINATION lib/cmake/csharpify/dotnet-deps 140 | FILES_MATCHING 141 | PATTERN "*.csproj" 142 | PATTERN "CMakeLists.txt" 143 | PATTERN "*.props" 144 | PATTERN "obj/*" EXCLUDE 145 | ) 146 | 147 | install(DIRECTORY ${CMAKE_SOURCE_DIR}/dotnet-deps/imports/ DESTINATION lib/cmake/csharpify/dotnet-deps/imports/ 148 | FILES_MATCHING 149 | PATTERN "*.props" 150 | ) 151 | 152 | include(CMakePackageConfigHelpers) 153 | 154 | configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/config.cmake.in 155 | "${CMAKE_CURRENT_BINARY_DIR}/CSharpifyConfig.cmake" 156 | INSTALL_DESTINATION lib/cmake/csharpify 157 | ) 158 | 159 | write_basic_package_version_file( 160 | "${CMAKE_CURRENT_BINARY_DIR}/CSharpifyConfigVersion.cmake" 161 | VERSION "${version}" 162 | COMPATIBILITY AnyNewerVersion 163 | ) 164 | 165 | install(FILES 166 | "${CMAKE_CURRENT_BINARY_DIR}/CSharpifyConfig.cmake" 167 | "${CMAKE_CURRENT_BINARY_DIR}/CSharpifyConfigVersion.cmake" 168 | DESTINATION lib/cmake/csharpify 169 | ) 170 | 171 | set(CPACK_SYSTEM_NAME "all") 172 | include(CPack) 173 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 6, 3 | "cmakeMinimumRequired": 4 | { 5 | "major": 3, 6 | "minor": 26, 7 | "patch": 0 8 | }, 9 | "configurePresets": 10 | [ 11 | { 12 | "name": "coreclr", 13 | "displayName": "CoreCLR", 14 | "description": "Build with CoreCLR", 15 | "binaryDir": "${sourceDir}/build/coreclr", 16 | "cacheVariables": 17 | { 18 | "DOTNET_RUNTIME": 19 | { 20 | "type": "STRING", 21 | "value": "coreclr" 22 | } 23 | } 24 | }, 25 | { 26 | "name": "mono", 27 | "displayName": "Mono", 28 | "description": "Build with Mono", 29 | "binaryDir": "${sourceDir}/build/mono", 30 | "cacheVariables": 31 | { 32 | "DOTNET_RUNTIME": 33 | { 34 | "type": "STRING", 35 | "value": "mono" 36 | } 37 | } 38 | }, 39 | { 40 | "name": "nativeaot", 41 | "displayName": "NativeAOT", 42 | "description": "Build with NativeAOT", 43 | "binaryDir": "${sourceDir}/build/nativeaot", 44 | "cacheVariables": 45 | { 46 | "DOTNET_RUNTIME": 47 | { 48 | "type": "STRING", 49 | "value": "nativeaot" 50 | } 51 | } 52 | } 53 | ], 54 | "buildPresets": 55 | [ 56 | { 57 | "name": "coreclr", 58 | "displayName": "CoreCLR", 59 | "description": "Build with CoreCLR", 60 | "configurePreset": "coreclr" 61 | }, 62 | { 63 | "name": "mono", 64 | "displayName": "Mono", 65 | "description": "Build with Mono", 66 | "configurePreset": "mono" 67 | }, 68 | { 69 | "name": "nativeaot", 70 | "displayName": "NativeAOT", 71 | "description": "Build with NativeAOT", 72 | "configurePreset": "nativeaot" 73 | } 74 | ], 75 | "packagePresets": 76 | [ 77 | { 78 | "name": "coreclr", 79 | "displayName": "Package", 80 | "description": "Package from the build/coreclr directory (all modes will be packaged, just pick the same preset that you used to configure)", 81 | "configurePreset": "coreclr", 82 | "generators": ["ZIP"] 83 | }, 84 | { 85 | "name": "mono", 86 | "displayName": "Package", 87 | "description": "Package from the build/mono directory (all modes will be packaged, just pick the same preset that you used to configure)", 88 | "configurePreset": "mono", 89 | "generators": ["ZIP"] 90 | }, 91 | { 92 | "name": "nativeaot", 93 | "displayName": "Package", 94 | "description": "Package from the build/nativeaot directory (all modes will be packaged, just pick the same preset that you used to configure)", 95 | "configurePreset": "nativeaot", 96 | "generators": ["ZIP"] 97 | } 98 | ] 99 | 100 | } -------------------------------------------------------------------------------- /GDC2024.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spoiledcat/csharpify/bb793eb9cfde0587ef1be39c8cd32a2e628fd450/GDC2024.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2024 Andreia Gaita (https://spoiledcat.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSharpify 2 | 3 | An example of how to embed C# in a C/C++ application, supporting Mono and CoreCLR on multiple platforms. 4 | 5 | This example initializes and runs [DearImGui](https://github.com/ocornut/imgui) with the SDL2+Vulkan backend, by taking the corresponding example source and replacing everything between `ImGui::NewFrame()` and `ImGui::Render()` with a call back to the csharpify main code, which then calls a C# method, on every frame. cimgui and the DearImGui C# bindings are included, so C# can call all the DearImGui APIs that the demo would normally call. 6 | 7 | The C declarations and trampoline methods are generated using a slightly modified version of [DNNE](https://github.com/shana/DNNE), a prototype project that generates native exports for C#. 8 | 9 | **NOTE**: This is all still a work in progress! It's only been tested on mac and windows, and things might be broken often while the rest of the platforms and embedding modes are added. 10 | 11 | ## How to build 12 | 13 | Requirements: 14 | - Cmake 3.26+ 15 | - .NET 8.0.101 - This is currently enforced with global.json, but there's no reason it shouldn't work with any .NET 7+ 16 | 17 | After cloning this repository, grab the submodules. 18 | 19 | ``` 20 | git submodule update --init 21 | ``` 22 | 23 | After building, all needed files should be in `build/[runtime]/native/bin`, where `runtime` is the runtime corresponding to the preset you chose. On Windows, it will be in `build/[runtime]/native/bin/Debug`, due to the way Visual Studio creates output directories. 24 | 25 | ### Mono 26 | 27 | ``` 28 | cmake --preset mono 29 | cmake --build --preset mono 30 | ``` 31 | 32 | ### CoreCLR 33 | 34 | ``` 35 | cmake --preset coreclr 36 | cmake --build --preset coreclr 37 | ``` 38 | 39 | ### AOT/NativeAOT 40 | 41 | TODO: Work in progress, coming soon. 42 | 43 | 44 | ## How to use this in your own project 45 | 46 | Running 47 | 48 | ``` 49 | cmake --install build/[runtime] 50 | ``` 51 | 52 | will create an install directory with the isolated header and source files and cmake files needed, without the DearImGui bits. You can use either runtime preset for this, files for all the runtime configurations will be included. 53 | 54 | ### Example of how to include csharpify in another CMake project 55 | 56 | A demo project with the files configured as below is in https://github.com/spoiledcat/csharpify-demo 57 | 58 | Add a NuGet.config file to the root of your project, so that the .NET runtime libraries can be in a known location for linking. 59 | 60 | ```NuGet.config 61 | 62 | 63 | 64 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | ``` 76 | 77 | Create a `packages` folder and copy over the `DNNE.2.0.6.2.nupkg` package into it, from the packages folder in this repository. 78 | 79 | Configure your CMakeLists.txt file to find the csharpify package, set up the dotnet-deps project and config.h, include paths and link flags. 80 | 81 | ```CMakeLists.txt 82 | cmake_minimum_required(VERSION 3.26) 83 | project(test) 84 | 85 | set(CMAKE_CXX_STANDARD 17) 86 | set(CMAKE_C_STANDARD 17) 87 | 88 | set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "") 89 | if(NOT CMAKE_BUILD_TYPE) 90 | set(CMAKE_BUILD_TYPE "Debug") 91 | endif() 92 | 93 | message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") 94 | 95 | find_package(CSharpify HINTS "${CMAKE_SOURCE_DIR}/../csharpify/install/lib/cmake") 96 | 97 | message(STATUS "${CMAKE_MODULE_PATH}") 98 | file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/packages") 99 | add_subdirectory("${CMAKE_SOURCE_DIR}/dotnet-deps") 100 | 101 | # This must come after including dotnet-deps 102 | include(CSharpifyDotnet) 103 | 104 | configure_file("${CSHARPIFY_CONFIG_H_IN}" config.h) 105 | 106 | list(APPEND dependencies packages) 107 | 108 | # Configuring paths and file lists for the dotnet build and publish steps 109 | cmake_path(APPEND PROJECT_SOURCE_DIR "main.csproj" OUTPUT_VARIABLE CSPROJ) 110 | cmake_path(GET CSPROJ STEM ASSEMBLYNAME) 111 | set(ASSEMBLYNAME "${ASSEMBLYNAME}" CACHE STRING "Assembly name") 112 | 113 | list(APPEND build_outputs ${ASSEMBLYNAME}.dll ${ASSEMBLYNAME}.pdb) 114 | if(DOTNET_PLATFORM STREQUAL "win" AND DOTNET_RUNTIME STREQUAL "coreclr") 115 | list(APPEND build_outputs ${ASSEMBLYNAME}.runtimeconfig.json) 116 | endif() 117 | 118 | set(publish_args "") 119 | set(publish_dir "${PROJECT_BINARY_DIR}/publish") 120 | set(bin_dir "${CMAKE_BINARY_DIR}") 121 | if(DOTNET_PLATFORM STREQUAL "win") 122 | set(bin_dir "${CMAKE_BINARY_DIR}/Debug") 123 | endif() 124 | 125 | file(GLOB cs_sources "${PROJECT_SOURCE_DIR}/*.cs") 126 | 127 | # Run dotnet build 128 | add_custom_command( 129 | OUTPUT "${PROJECT_BINARY_DIR}/.stamp" ${build_outputs} "${PROJECT_SOURCE_DIR}/generated/exports.g.c" 130 | COMMAND ${CMAKE_COMMAND} -E env "PATH=${ORIGINAL_PATH}" ${DOTNET} build \"${CSPROJ}\" --nologo -c $ -o \"${PROJECT_BINARY_DIR}\" /p:UseMonoRuntime=$,true,false> 131 | COMMAND ${CMAKE_COMMAND} -E touch "${PROJECT_BINARY_DIR}/.stamp" 132 | BYPRODUCTS "${PROJECT_SOURCE_DIR}/generated/dnne.h" "${PROJECT_SOURCE_DIR}/generated/exports.h" "${PROJECT_SOURCE_DIR}/generated/platform.c" 133 | DEPENDS "Directory.Build.props" "Directory.Build.targets" ${cs_sources} "${CSPROJ}" 134 | ) 135 | add_custom_target(build DEPENDS ${build_outputs} "${PROJECT_SOURCE_DIR}/generated/exports.g.c") 136 | 137 | # Run dotnet publish 138 | add_custom_command( 139 | OUTPUT "${publish_dir}/.stamp" "${publish_dir}/${ASSEMBLYNAME}.dll" "${publish_dir}/System.dll" 140 | COMMAND ${CMAKE_COMMAND} -E env "PATH=${ORIGINAL_PATH}" ${DOTNET} publish \"${CSPROJ}\" ${publish_args} --sc -r ${RID} --nologo -c $ -o \"${publish_dir}\" /p:UseMonoRuntime=$,true,false> 141 | COMMAND ${CMAKE_COMMAND} -E touch "${publish_dir}/.stamp" 142 | DEPENDS "Directory.Build.props" "Directory.Build.targets" ${cs_sources} "${CSPROJ}" 143 | ) 144 | add_custom_target(publish DEPENDS "${publish_dir}/${ASSEMBLYNAME}.dll") 145 | 146 | if(NOT(DOTNET_PLATFORM STREQUAL "win" AND DOTNET_RUNTIME STREQUAL "coreclr")) 147 | add_custom_target(link_sdk 148 | COMMAND ${CMAKE_COMMAND} -E create_symlink "${publish_dir}" "${bin_dir}/sdk" 149 | DEPENDS "${publish_dir}/System.dll" 150 | ) 151 | list(APPEND dependencies link_sdk) 152 | endif() 153 | 154 | 155 | list(APPEND export_sources "${PROJECT_SOURCE_DIR}/generated/exports.g.c") 156 | list(APPEND export_includes "${PROJECT_SOURCE_DIR}/generated") 157 | 158 | if(DOTNET_PLATFORM STREQUAL "win") 159 | list(APPEND export_sources "${PROJECT_SOURCE_DIR}/generated/platform.c") 160 | endif() 161 | 162 | add_executable(test main.cpp ${export_sources}) 163 | target_include_directories(test PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_BINARY_DIR}/include" "${DOTNET_INCLUDE_DIRS}" ${export_includes} ) 164 | target_compile_definitions(test PRIVATE DNNE_COMPILE_AS_SOURCE DNNE_SELF_CONTAINED_RUNTIME) 165 | 166 | if(RUNTIME_MONO) 167 | list(APPEND dependencies csharpify_mono) 168 | target_link_libraries(test PRIVATE csharpify_mono ${CORECLR}) 169 | elseif(RUNTIME_CORECLR) 170 | list(APPEND dependencies csharpify_coreclr) 171 | target_link_libraries(test PRIVATE csharpify_coreclr ${CORECLR}) 172 | endif() 173 | 174 | add_dependencies(test packages ${dependencies}) 175 | ``` 176 | 177 | Include the headers in your source. 178 | 179 | ```main.cpp 180 | #include "config.h" 181 | #include "common.h" 182 | #include "managed_bridge.h" 183 | #include "managed_exports.h" 184 | 185 | int main(int argc, char** argv) 186 | { 187 | } 188 | ``` -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | { set +x; } 2>/dev/null 4 | SOURCE=$0 5 | DIR="$( pwd )" 6 | 7 | CONFIGURATION=Debug 8 | PRESET= 9 | ARGSONLY=0 10 | ARGS= 11 | 12 | while (( "$#" )); do 13 | if [[ x"$ARGSONLY" == x"1" ]]; then 14 | ARGS="${ARGS} $1" 15 | shift 16 | continue 17 | fi 18 | 19 | case "$1" in 20 | -d|--debug) 21 | CONFIGURATION="Debug" 22 | ;; 23 | -r|--release) 24 | CONFIGURATION="Release" 25 | ;; 26 | -c|--configuration) 27 | shift 28 | CONFIGURATION=$1 29 | ;; 30 | pc|--coreclr) 31 | PRESET=coreclr 32 | ;; 33 | pm|--mono) 34 | PRESET=mono 35 | ;; 36 | pn|--nativeaot) 37 | PRESET=nativeaot 38 | ;; 39 | -v|--verbose) 40 | ARGS="${ARGS} --verbose" 41 | ;; 42 | --args) 43 | ARGSONLY=1 44 | ;; 45 | --trace) 46 | { set -x; } 2>/dev/null 47 | ;; 48 | *) 49 | ARGS="${ARGS} $1" 50 | ;; 51 | esac 52 | shift 53 | done 54 | 55 | cmake --preset $PRESET 56 | cmake --build --preset $PRESET 57 | cpack --preset $PRESET 58 | cp build/$PRESET/csharpify-*-all.zip . -------------------------------------------------------------------------------- /cmake/CSharpifyDefinitions.cmake: -------------------------------------------------------------------------------- 1 | option(RUNTIME_CORECLR "Use CoreCLR" 0) 2 | option(RUNTIME_MONO "Use Mono" 0) 3 | option(RUNTIME_NATIVEAOT "Use NativeAOT" 0) 4 | option(DOTNET_ARCH "Target Arch" "") 5 | option(DOTNET_PLATFORM "Target platform" "") 6 | option(DOTNET_RUNTIME "Target runtime" "") 7 | 8 | if(NOT DOTNET_ARCH) 9 | string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" DOTNET_ARCH) 10 | string(REPLACE "amd" "x" DOTNET_ARCH "${DOTNET_ARCH}") 11 | set(DOTNET_ARCH "${DOTNET_ARCH}" CACHE STRING ".NET Arch" FORCE) 12 | else(if NOT DEFINED CACHE{DOTNET_ARCH}) 13 | set(DOTNET_ARCH "${DOTNET_ARCH}" CACHE STRING ".NET Arch") 14 | endif() 15 | 16 | if(NOT DOTNET_PLATFORM) 17 | if(CMAKE_HOST_APPLE) 18 | set(DOTNET_PLATFORM "osx" CACHE STRING ".NET Platform" FORCE) 19 | elseif(CMAKE_HOST_WIN32) 20 | set(DOTNET_PLATFORM "win" CACHE STRING ".NET Platform" FORCE) 21 | else() 22 | set(DOTNET_PLATFORM "linux" CACHE STRING ".NET Platform" FORCE) 23 | endif() 24 | else(if NOT DEFINED CACHE{DOTNET_PLATFORM}) 25 | set(DOTNET_PLATFORM "${DOTNET_PLATFORM}" CACHE STRING ".NET Platform") 26 | endif() 27 | 28 | if(DOTNET_PLATFORM STREQUAL "osx" OR DOTNET_PLATFORM STREQUAL "win" OR DOTNET_PLATFORM STREQUAL "linux") 29 | set(DEFAULT_RUNTIME "coreclr") 30 | else() 31 | set(DEFAULT_RUNTIME "mono") 32 | endif() 33 | 34 | if(NOT RUNTIME_CORECLR AND NOT RUNTIME_MONO AND NOT RUNTIME_NATIVEAOT) 35 | if(NOT DOTNET_RUNTIME) 36 | set(DOTNET_RUNTIME "${DEFAULT_RUNTIME}" CACHE STRING ".NET Runtime" FORCE) 37 | else(if NOT DEFINED CACHE{DOTNET_RUNTIME}) 38 | set(DOTNET_RUNTIME "${DOTNET_RUNTIME}" CACHE STRING ".NET Runtime") 39 | endif() 40 | elseif(RUNTIME_MONO) 41 | set(DOTNET_RUNTIME "mono") 42 | elseif(RUNTIME_CORECLR) 43 | set(DOTNET_RUNTIME "coreclr") 44 | elseif(RUNTIME_NATIVEAOT) 45 | set(DOTNET_RUNTIME "nativeaot") 46 | endif() 47 | 48 | 49 | if (DOTNET_RUNTIME STREQUAL "coreclr") 50 | set(RUNTIME_CORECLR 1) 51 | set(runtimesuffix "") 52 | elseif(DOTNET_RUNTIME STREQUAL "mono") 53 | set(RUNTIME_MONO 1) 54 | set(runtimesuffix "Mono.") 55 | else() 56 | set(RUNTIME_NATIVEAOT 1) 57 | set(runtimesuffix "NativeAOT.") 58 | endif() 59 | 60 | -------------------------------------------------------------------------------- /cmake/CSharpifyDotnet.cmake: -------------------------------------------------------------------------------- 1 | find_program(DOTNET "dotnet") 2 | if ("${DOTNET}" STREQUAL "DOTNET-NOTFOUND") 3 | message(FATAL_ERROR "dotnet could not be found!") 4 | else() 5 | execute_process(COMMAND "${DOTNET}" --version 6 | OUTPUT_VARIABLE DOTNET_VERSION 7 | OUTPUT_STRIP_TRAILING_WHITESPACE 8 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") 9 | endif() 10 | 11 | set(ORIGINAL_PATH $ENV{PATH}) 12 | set(DOTNET_VERSION ${DOTNET_VERSION}) 13 | 14 | # Find dotnet versions 15 | cmake_path(GET DOTNET PARENT_PATH DOTNET_PATH) 16 | cmake_path(APPEND DOTNET_PATH "sdk/${DOTNET_VERSION}" OUTPUT_VARIABLE DOTNET_PATH) 17 | cmake_path(APPEND DOTNET_PATH "Microsoft.NETCoreSdk.BundledVersions.props" OUTPUT_VARIABLE VERSIONS_PROPS) 18 | file(READ "${VERSIONS_PROPS}" VersionProps_CONTENT) 19 | string(REGEX MATCH "(.*)" PARSED_DOTNET_SDK_VERSION "${VersionProps_CONTENT}") 20 | set(PARSED_DOTNET_SDK_VERSION "${CMAKE_MATCH_1}") 21 | 22 | #message(STATUS "Using ${DOTNET} version ${DOTNET_VERSION} sdk ${PARSED_DOTNET_SDK_VERSION}") 23 | 24 | string(REGEX MATCH "([0-9]+)\.([0-9]+)\\.([0-9]+)" VERSION_PARTS "${DOTNET_VERSION}") 25 | set(DOTNET_MAJOR "${CMAKE_MATCH_1}") 26 | set(DOTNET_MINOR "${CMAKE_MATCH_2}") 27 | set(DOTNET_PATCH "${CMAKE_MATCH_3}") 28 | set(DOTNET_SDK_VERSION "${PARSED_DOTNET_SDK_VERSION}" CACHE STRING "..NET SDK Version" FORCE) 29 | set(DOTNET_VERSION_MAJOR "${DOTNET_MAJOR}" CACHE STRING ".NET SDK Version Major" FORCE) 30 | set(DOTNET_VERSION_MINOR "${DOTNET_MINOR}" CACHE STRING ".NET SDK Version Minor" FORCE) 31 | set(DOTNET_VERSION_PATCH "${DOTNET_PATCH}" CACHE STRING ".NET SDK Version Patch" FORCE) 32 | set(DOTNET_SDK_VERSION "${PARSED_DOTNET_SDK_VERSION}" CACHE STRING "..NET SDK Version" FORCE) 33 | 34 | message(STATUS ".NET SDK:${PARSED_DOTNET_SDK_VERSION}") 35 | message(STATUS ".NET Version:${DOTNET_MAJOR}.${DOTNET_MINOR}.${DOTNET_PATCH}") 36 | 37 | cmake_path(APPEND CMAKE_SOURCE_DIR ".packages" OUTPUT_VARIABLE DOTNET_PACKAGES_PATH) 38 | 39 | set(RID "${DOTNET_PLATFORM}-${DOTNET_ARCH}" CACHE STRING ".NET Runtime Identifier" FORCE) 40 | 41 | # this is useful on all platforms for the coreclr definitions 42 | set(DOTNET_APPHOST_PATH 43 | "${DOTNET_PACKAGES_PATH}/microsoft.netcore.app.host.win-x64/${PARSED_DOTNET_SDK_VERSION}/runtimes/win-x64/native" 44 | CACHE STRING ".NET App Host" FORCE 45 | ) 46 | 47 | set(DOTNET_SDK_PATH_ROOT 48 | "${DOTNET_PACKAGES_PATH}/microsoft.netcore.app.runtime.${runtimesuffix}${RID}/${PARSED_DOTNET_SDK_VERSION}/runtimes/${RID}" 49 | CACHE STRING ".NET SDK root" FORCE 50 | ) 51 | 52 | set(DOTNET_SDK_NUSPEC 53 | "${DOTNET_PACKAGES_PATH}/microsoft.netcore.app.runtime.${runtimesuffix}${RID}/${PARSED_DOTNET_SDK_VERSION}/microsoft.netcore.app.runtime.${runtimesuffix}${RID}.nuspec" 54 | CACHE STRING ".NET SDK nuspec marker" FORCE 55 | ) 56 | 57 | set(DOTNET_SDK_PATH "${DOTNET_SDK_PATH_ROOT}/lib/net${DOTNET_MAJOR}.${DOTNET_MINOR}" CACHE STRING ".NET SDK path" FORCE) 58 | set(DOTNET_LIBRARY_PATH "${DOTNET_SDK_PATH_ROOT}/native" CACHE STRING ".NET lib path for linking" FORCE) 59 | 60 | if(NOT DOTNET_INCLUDE_DIRS) 61 | set(DOTNET_INCLUDE_DIRS "") 62 | endif() 63 | 64 | if(RUNTIME_MONO) 65 | list(APPEND DOTNET_INCLUDE_DIRS "${DOTNET_LIBRARY_PATH}/include/mono-2.0/") 66 | endif() 67 | 68 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") 69 | 70 | if(RUNTIME_CORECLR) 71 | if(DOTNET_PLATFORM STREQUAL "win") 72 | list(APPEND DOTNET_INCLUDE_DIRS "${DOTNET_APPHOST_PATH}") 73 | else() 74 | find_library(CORECLR coreclr PATHS "${DOTNET_LIBRARY_PATH}") 75 | endif() 76 | elseif(RUNTIME_MONO) 77 | find_library(CORECLR coreclr PATHS "${DOTNET_LIBRARY_PATH}") 78 | endif() 79 | 80 | message(STATUS ".NET RID: ${RID}") 81 | message(STATUS ".NET Runtime: ${DOTNET_RUNTIME}") 82 | message(STATUS ".NET SDK: ${DOTNET_SDK_PATH_ROOT}") 83 | -------------------------------------------------------------------------------- /cmake/PatchFile.cmake: -------------------------------------------------------------------------------- 1 | # use GNU Patch from any platform 2 | 3 | if(WIN32) 4 | # prioritize Git Patch on Windows as other Patches may be very old and incompatible. 5 | find_package(Git) 6 | if(Git_FOUND) 7 | get_filename_component(GIT_DIR ${GIT_EXECUTABLE} DIRECTORY) 8 | get_filename_component(GIT_DIR ${GIT_DIR} DIRECTORY) 9 | endif() 10 | endif() 11 | 12 | find_program(PATCH 13 | NAMES patch 14 | HINTS ${GIT_DIR} 15 | PATH_SUFFIXES usr/bin 16 | ) 17 | 18 | if(NOT PATCH) 19 | message(FATAL_ERROR "Did not find GNU Patch") 20 | endif() 21 | 22 | if(out_file) 23 | execute_process(COMMAND ${PATCH} ${in_file} --input=${patch_file} --output=${out_file} --ignore-whitespace -N -s 24 | TIMEOUT 15 25 | OUTPUT_VARIABLE PATCHERR 26 | ERROR_VARIABLE PATCHERR 27 | RESULT_VARIABLE ret 28 | ) 29 | else() 30 | execute_process(COMMAND ${PATCH} ${in_file} --input=${patch_file} --ignore-whitespace -N -s 31 | TIMEOUT 15 32 | OUTPUT_VARIABLE PATCHERR 33 | ERROR_VARIABLE PATCHERR 34 | RESULT_VARIABLE ret 35 | ) 36 | endif() 37 | 38 | if(NOT ret EQUAL 0 AND NOT(PATCHERR MATCHES "Skipping patch") AND NOT(PATCHERR MATCHES "previously applied")) 39 | message(FATAL_ERROR "Failed to apply patch ${patch_file} to ${in_file} with ${PATCH}") 40 | endif() 41 | -------------------------------------------------------------------------------- /config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include ("${CMAKE_CURRENT_LIST_DIR}/CSharpifyCoreCLR.cmake") 4 | include ("${CMAKE_CURRENT_LIST_DIR}/CSharpifyMono.cmake") 5 | include ("${CMAKE_CURRENT_LIST_DIR}/CSharpifyDefinitions.cmake") 6 | include ("${CMAKE_CURRENT_LIST_DIR}/CSharpifyDotnet.cmake") 7 | 8 | execute_process( 9 | COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different "${CMAKE_CURRENT_LIST_DIR}/dotnet-deps/" "${CMAKE_SOURCE_DIR}/dotnet-deps/" 10 | ) 11 | 12 | set(CSHARPIFY_CONFIG_H_IN "${CMAKE_CURRENT_LIST_DIR}/config.h.in") 13 | 14 | check_required_components(CSharpify) -------------------------------------------------------------------------------- /dotnet-deps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(packages) 2 | 3 | # ensure packages are restored on first configure 4 | execute_process( 5 | COMMAND ${CMAKE_COMMAND} -E env "PATH=${ORIGINAL_PATH}" ${DOTNET} "restore" 6 | WORKING_DIRECTORY "${packages_SOURCE_DIR}" 7 | ) 8 | 9 | file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include") 10 | configure_file("${DOTNET_APPHOST_PATH}/coreclr_delegates.h" "${CMAKE_BINARY_DIR}/include/coreclr_delegates.h") 11 | 12 | file(GLOB props "${packages_SOURCE_DIR}/imports/*.props") 13 | 14 | # # if dependencies change, this will run again at build time 15 | add_custom_command( 16 | OUTPUT "${packages_SOURCE_DIR}/.stamp" 17 | "${packages_SOURCE_DIR}/obj/project.assets.json" 18 | "${CMAKE_BINARY_DIR}/include/coreclr_delegates.h" 19 | "${DOTNET_SDK_NUSPEC}" 20 | COMMAND ${CMAKE_COMMAND} -E env "PATH=${ORIGINAL_PATH}" ${DOTNET} "restore" 21 | COMMAND ${CMAKE_COMMAND} -E copy -t "${CMAKE_BINARY_DIR}/include/" "${DOTNET_APPHOST_PATH}/coreclr_delegates.h" 22 | COMMAND ${CMAKE_COMMAND} -E touch ".stamp" 23 | WORKING_DIRECTORY "${packages_SOURCE_DIR}" 24 | DEPENDS packages.csproj ${props} 25 | ) 26 | 27 | add_custom_target(packages DEPENDS "${CMAKE_BINARY_DIR}/include/coreclr_delegates.h" "${packages_SOURCE_DIR}/obj/project.assets.json" "${DOTNET_SDK_NUSPEC}") 28 | 29 | list(APPEND headers "${CMAKE_BINARY_DIR}/include/coreclr_delegates.h") 30 | list(APPEND dirs "${CMAKE_BINARY_DIR}/include") 31 | 32 | set(SHARED_HEADERS ${headers} PARENT_SCOPE) 33 | set(SHARED_INCLUDE_DIRS ${dirs} PARENT_SCOPE) 34 | -------------------------------------------------------------------------------- /dotnet-deps/imports/android-arm64-mono.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/android-x64-mono.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/ios-arm64-mono.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/ios-arm64-nativeaot.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/linux-arm64-coreclr.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/linux-arm64-mono.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/linux-x64-coreclr.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/linux-x64-mono.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/linux_bionic-arm64-nativeaot.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/linux_bionic-x64-nativeaot.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/osx-arm64-coreclr.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/osx-arm64-mono.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/osx-arm64-nativeaot.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/osx-x64-coreclr.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/osx-x64-mono.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/osx-x64-nativeaot.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/plat-arch-runtime.props.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/win-x64-coreclr.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/imports/win-x64-mono.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileName.Split('-')[0]) 5 | $(CSharpify_Prop_ThisPlat.Replace('_','-')) 6 | $(CSharpify_Prop_ThisPlat.Split('-')[0]) 7 | $(MSBuildThisFileName.Split('-')[1]) 8 | $(MSBuildThisFileName.Split('-')[2]) 9 | 10 | $(CSharpify_Prop_Platforms);$(CSharpify_Prop_ThisPlat) 11 | 12 | $(CSharpify_Prop_Platforms_x64);$(CSharpify_Prop_ThisPlat) 13 | $(CSharpify_Prop_Platforms_arm64);$(CSharpify_Prop_ThisPlat) 14 | $(CSharpify_Prop_Platforms_x86);$(CSharpify_Prop_ThisPlat) 15 | $(CSharpify_Prop_Platforms_arm);$(CSharpify_Prop_ThisPlat) 16 | 17 | $(CSharpify_Prop_Platforms_mono);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 18 | $(CSharpify_Prop_Platforms_coreclr);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 19 | $(CSharpify_Prop_Platforms_nativeaot);$(CSharpify_Prop_ThisPlat)-$(CSharpify_Prop_ThisArch) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dotnet-deps/other-imports.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /dotnet-deps/packages.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net$(BundledNETCoreAppTargetFrameworkVersion) 4 | $(CustomDotNetVersion) 5 | $(BundledNETCoreAppPackageVersion) 6 | $(NoWarn);NU1505 7 | 8 | 9 | 10 | arm64 11 | arm 12 | x64 13 | x86 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /managed/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(csharpify_managed) 2 | 3 | cmake_path(APPEND PROJECT_SOURCE_DIR "managed.csproj" OUTPUT_VARIABLE CSPROJ) 4 | cmake_path(APPEND PROJECT_BINARY_DIR "publish" OUTPUT_VARIABLE csharpify_managed_PUBLISH_DIR) 5 | cmake_path(APPEND PROJECT_SOURCE_DIR "generated" OUTPUT_VARIABLE generated_INCLUDE_DIR) 6 | cmake_path(ABSOLUTE_PATH generated_INCLUDE_DIR BASE_DIRECTORY "${CMAKE_SOURCE_DIR}" NORMALIZE OUTPUT_VARIABLE generated_INCLUDE_DIR) 7 | set(generated_INCLUDE_DIR "${generated_INCLUDE_DIR}" PARENT_SCOPE) 8 | set(csharpify_managed_PUBLISH_DIR "${csharpify_managed_PUBLISH_DIR}" PARENT_SCOPE) 9 | cmake_path(GET CSPROJ STEM ASSEMBLYNAME) 10 | set(ASSEMBLYNAME "${ASSEMBLYNAME}" CACHE STRING "Assembly name") 11 | 12 | set(publish_args "") 13 | set(dotnet_publish_dir "${csharpify_managed_PUBLISH_DIR}/publish") 14 | set(dotnet_sc_dir "${csharpify_managed_PUBLISH_DIR}/sc") 15 | set(bin_dir "${CMAKE_BINARY_DIR}/native") 16 | set(bundle_dir "${CMAKE_BINARY_DIR}/bin") 17 | 18 | configure_file("${CMAKE_CURRENT_LIST_DIR}/Directory.Build.props.in" "${CMAKE_CURRENT_LIST_DIR}/Directory.Build.props") 19 | 20 | list(APPEND build_outputs ${ASSEMBLYNAME}.dll ${ASSEMBLYNAME}.pdb) 21 | if(DOTNET_PLATFORM STREQUAL "win" AND DOTNET_RUNTIME STREQUAL "coreclr") 22 | list(APPEND build_outputs ${ASSEMBLYNAME}.runtimeconfig.json) 23 | endif() 24 | 25 | add_custom_command( 26 | OUTPUT ${build_outputs} "${generated_INCLUDE_DIR}/exports.g.c" 27 | COMMAND ${CMAKE_COMMAND} -E env "PATH=${ORIGINAL_PATH}" ${DOTNET} build \"${CSPROJ}\" --nologo -c $ -o \"${PROJECT_BINARY_DIR}\" /p:UseMonoRuntime=$,true,false> 28 | BYPRODUCTS "${generated_INCLUDE_DIR}/dnne.h" "${generated_INCLUDE_DIR}/exports.h" 29 | DEPENDS "Directory.Build.props" "Directory.Build.targets" "main.cs" "managed.csproj" 30 | ) 31 | 32 | add_custom_target(build DEPENDS ${build_outputs} "${generated_INCLUDE_DIR}/exports.g.c") 33 | 34 | list(APPEND binaries "${bin_dir}/${ASSEMBLYNAME}.dll") 35 | 36 | add_custom_command( 37 | OUTPUT "${dotnet_publish_dir}/${ASSEMBLYNAME}.dll" 38 | COMMAND ${CMAKE_COMMAND} -E env "PATH=${ORIGINAL_PATH}" ${DOTNET} publish \"${CSPROJ}\" ${publish_args} --nologo -c $ -o \"${dotnet_publish_dir}\" /p:UseMonoRuntime=$,true,false> 39 | DEPENDS "Directory.Build.props" "Directory.Build.targets" "main.cs" "managed.csproj" 40 | ) 41 | 42 | list(APPEND binaries "${dotnet_publish_dir}/${ASSEMBLYNAME}.dll") 43 | 44 | # Bundle everything into a runnable directory 45 | file(MAKE_DIRECTORY "${bin_dir}") 46 | 47 | if(NOT DOTNET_PLATFORM STREQUAL "win" OR NOT DOTNET_RUNTIME STREQUAL "coreclr") 48 | add_custom_command( 49 | OUTPUT "${bin_dir}/${ASSEMBLYNAME}.dll" 50 | COMMAND ${CMAKE_COMMAND} -E env "PATH=${ORIGINAL_PATH}" ${DOTNET} publish \"${CSPROJ}\" ${publish_args} --nologo -c $ -o \"${bin_dir}\" /p:UseMonoRuntime=$,true,false> 51 | DEPENDS "Directory.Build.props" "Directory.Build.targets" "main.cs" "managed.csproj" 52 | ) 53 | 54 | add_custom_target(managed_publish DEPENDS "${dotnet_publish_dir}/${ASSEMBLYNAME}.dll" "${bin_dir}/${ASSEMBLYNAME}.dll") 55 | 56 | add_custom_command( 57 | OUTPUT "${dotnet_sc_dir}/${ASSEMBLYNAME}.dll" "${dotnet_sc_dir}/System.dll" 58 | COMMAND ${CMAKE_COMMAND} -E env "PATH=${ORIGINAL_PATH}" ${DOTNET} publish \"${CSPROJ}\" ${publish_args} --sc -r ${RID} --nologo -c $ -o \"${dotnet_sc_dir}\" /p:UseMonoRuntime=$,true,false> 59 | DEPENDS "Directory.Build.props" "Directory.Build.targets" "main.cs" "managed.csproj" 60 | ) 61 | 62 | add_custom_target(managed_sc DEPENDS "${dotnet_sc_dir}/${ASSEMBLYNAME}.dll") 63 | list(APPEND binaries "${dotnet_sc_dir}/${ASSEMBLYNAME}.dll") 64 | 65 | endif() 66 | 67 | if(NOT(DOTNET_PLATFORM STREQUAL "win" AND DOTNET_RUNTIME STREQUAL "coreclr")) 68 | add_custom_target(copy_sdk 69 | COMMAND ${CMAKE_COMMAND} -E create_symlink "${dotnet_sc_dir}" "${bin_dir}/sdk" 70 | DEPENDS "${dotnet_sc_dir}/System.dll" 71 | ) 72 | 73 | list(APPEND sdk copy_sdk) 74 | endif() 75 | 76 | add_custom_target(csharpify_managed DEPENDS ${binaries}) 77 | 78 | # On Windows, we need to have a shared/Microsoft.NETCore.App/${DOTNET_SDK_VERSION} folder 79 | # with the sdk, which comes from ${DOTNET_SDK_PATH} 80 | # coreclr.dll et al from ${DOTNET_LIBRARY_PATH} go into the shared folder 81 | # and hostfxr.dll goes into its own folder (it must be three levels down 82 | # because it's hardcoded to search for the sdk three levels up, it's stupid) 83 | if(DOTNET_PLATFORM STREQUAL "win" AND DOTNET_RUNTIME STREQUAL "coreclr") 84 | foreach(thing ${build_outputs}) 85 | cmake_path(GET thing FILENAME filename) 86 | list(APPEND bundle_outputs "${bundle_dir}/${CMAKE_BUILD_TYPE}/${filename}") 87 | endforeach() 88 | 89 | list(APPEND bundle_outputs 90 | "${bundle_dir}/$/${ASSEMBLYNAME}.dll" 91 | "${bundle_dir}/$/shared/Microsoft.NETCore.App/${DOTNET_SDK_VERSION}/Microsoft.NETCore.App.runtimeconfig.json" 92 | "${bundle_dir}/$/shared/Microsoft.NETCore.App/${DOTNET_SDK_VERSION}/hostpolicy.dll" 93 | "${bundle_dir}/$/shared/Microsoft.NETCore.App/${DOTNET_SDK_VERSION}/coreclr.dll" 94 | "${bundle_dir}/$/shared/host/fxr/hostfxr.dll" 95 | ) 96 | 97 | # Bundle everything into a runnable directory 98 | add_custom_command( 99 | OUTPUT ${bundle_outputs} 100 | COMMAND ${CMAKE_COMMAND} -E make_directory "${bundle_dir}/$" 101 | COMMAND ${CMAKE_COMMAND} -E copy -t "${bundle_dir}/$" ${build_outputs} "${bin_dir}/${ASSEMBLYNAME}.dll" 102 | COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${dotnet_publish_dir} "${bundle_dir}/$" 103 | COMMAND ${CMAKE_COMMAND} -E make_directory "${bundle_dir}/$/shared/Microsoft.NETCore.App" 104 | COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different "${DOTNET_SDK_PATH}" "${bundle_dir}/$/shared/Microsoft.NETCore.App/${DOTNET_SDK_VERSION}" 105 | COMMAND ${CMAKE_COMMAND} -E copy -t "${bundle_dir}/$/shared/Microsoft.NETCore.App/${DOTNET_SDK_VERSION}" "${DOTNET_LIBRARY_PATH}/hostpolicy.dll" 106 | COMMAND ${CMAKE_COMMAND} -E copy -t "${bundle_dir}/$/shared/Microsoft.NETCore.App/${DOTNET_SDK_VERSION}" "${DOTNET_LIBRARY_PATH}/hostpolicy.dll" "${DOTNET_LIBRARY_PATH}/hostfxr.dll" 107 | COMMAND ${CMAKE_COMMAND} -E make_directory "${bundle_dir}/$/shared/host/fxr" 108 | COMMAND ${CMAKE_COMMAND} -E copy -t "${bundle_dir}/$/shared/host/fxr" "${DOTNET_LIBRARY_PATH}/hostfxr.dll" 109 | COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different "${DOTNET_LIBRARY_PATH}" "${bundle_dir}/$/shared/Microsoft.NETCore.App/${DOTNET_SDK_VERSION}" 110 | DEPENDS ${build_outputs} "${bin_dir}/${ASSEMBLYNAME}.dll" 111 | ) 112 | 113 | add_custom_target(csharpify_managed_bundled DEPENDS csharpify_managed ${bundle_outputs}) 114 | else() 115 | add_custom_target(csharpify_managed_bundled DEPENDS ${sdk}) 116 | add_dependencies(csharpify_managed csharpify_managed_bundled) 117 | endif() 118 | -------------------------------------------------------------------------------- /managed/Directory.Build.props.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | $([MSBuild]::ValueOrDefault('@CMAKE_BINARY_DIR@', '').Replace('/', '\'))\ 4 | $(RepoBuildPath)bin\ 5 | $(RepoBuildPath)obj\ 6 | $(RepoObjPath) 7 | $(RepoBinPath) 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /managed/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | false 6 | $(MSBuildProjectDirectory)\generated\ 7 | exports.h 8 | exports.g.c 9 | 10 | 11 | 12 | 13 | $(CSharpify_GeneratedHeader) 14 | 15 | 16 | $(CSharpify_GeneratedSource) 17 | 18 | 19 | dnne.h 20 | 21 | 22 | platform.c 23 | 24 | 25 | 26 | 27 | 32 | 33 | 34 | -d "$(DocumentationFile)" 35 | 36 | 37 | dotnet $([System.IO.Path]::GetFullPath('$(PkgDNNE)\tools\dnne-gen.dll')) 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /managed/main.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Runtime.InteropServices.Marshalling; 6 | using System.Text; 7 | using ImGuiNET; 8 | using SDL2; 9 | 10 | public partial class Program { 11 | 12 | [UnmanagedCallersOnly()] 13 | private static void OnStart() { 14 | // called when starting up 15 | int a = 0; 16 | } 17 | 18 | 19 | [UnmanagedCallersOnly()] 20 | private static void OnUpdate() 21 | { 22 | //ImGui.ShowDemoWindow(); 23 | 24 | ImGui.Begin("My Cool Window"); 25 | 26 | ImGui.Text("Some text!"); 27 | 28 | bool boolWrong = BoolWithoutMarshalling(); 29 | ImGui.Text($"Unmarshalled bool value. Should be 'False', it's '{boolWrong}'??"); 30 | 31 | 32 | 33 | //bool boolRight = ReturningBool(); 34 | //ImGui.Text($"Marshalled bool value. Should be 'False', it's '{boolRight}'"); 35 | 36 | //boolRight = BoolMarshaledAsI1(); 37 | //ImGui.Text($"Marshalled as I1 bool value. Should be 'False', it's '{boolRight}'"); 38 | 39 | //string val = BoolMarshaledPinvoke(); 40 | //ImGui.Text($"Marshalled Pinvoke bool value. Should be 'False', it's '{val}'"); 41 | 42 | //boolRight = ReturningByte1() != 0; 43 | //ImGui.Text($"Unmarshalled LibraryImport byte value. Should be 'False', it's '{boolRight}'"); 44 | 45 | //boolRight = ReturningByte2() != 0; 46 | //ImGui.Text($"Unmarshalled DllImport byte value. Should be 'False', it's '{boolRight}'"); 47 | 48 | 49 | ImGui.End(); 50 | } 51 | 52 | 53 | // This one is not marshalled so the native side has to take care of it 54 | // LibraryImport cannot be used with a bool return value because it will 55 | // refuse (rightly) to generate marshalling information for bools 56 | // For this example we use a direct pinvoke to see what happens. 57 | [DllImport("__Internal", EntryPoint = "ReturningBool")] 58 | internal static extern bool BoolWithoutMarshalling(); 59 | 60 | 61 | 62 | // Marshalling the 8-bit value that the native side is returning into a 32-bit c# bool. 63 | // LibraryImport looks at the type used by Convert* methods in the marshaller and 64 | // generates a PInvoke of that type (byte in this case), and then the BoolMarshaller is 65 | // called to convert the value to the type defined by the CustomMarshaller attribute (bool) 66 | [LibraryImport("__Internal")] 67 | [return: MarshalUsing(typeof(BoolMarshaller))] internal static partial bool ReturningBool(); 68 | 69 | // Same as above, only without the marshaller but still with LibraryImport. 70 | // LibraryImport cannot be used with a bool return value because it will 71 | // refuse (rightly) to generate marshalling information for bools, so we have to use a byte 72 | // and the caller has to do the conversion. 73 | [LibraryImport("__Internal", EntryPoint = "ReturningBool")] 74 | internal static partial byte ReturningByte1(); 75 | 76 | // Same as above, only without the automatic marshaller and using direct pinvoke 77 | [DllImport("__Internal", EntryPoint = "ReturningBool")] 78 | internal static extern byte ReturningByte2(); 79 | 80 | // Direct pinvoke with DllImport also supports marshalling of types, but it only 81 | // supports a set of type conversions as defined in the UnmanagedType enum. 82 | // For more complex conversions, you have to implement the 83 | // System.Runtime.InteropServices.ICustomMarshaler interface 84 | [DllImport("__Internal", EntryPoint = "ReturningBool")] 85 | [return: MarshalAs(UnmanagedType.I1)] internal static extern bool BoolMarshaledAsI1(); 86 | 87 | // Custom marshallers with DllImport are only allowed on reference types so we're going to 88 | // make a reference type just for this example 89 | [DllImport("__Internal", EntryPoint = "ReturningBool")] 90 | [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(DllImportBoolMarshaler))] internal static extern string BoolMarshaledPinvoke(); 91 | 92 | 93 | 94 | 95 | [UnmanagedCallersOnly] 96 | public static unsafe void UpdateStructField(MyData* d) 97 | { 98 | d->field1 += d->field2; 99 | } 100 | 101 | 102 | [CustomMarshaller(typeof(bool), MarshalMode.Default, typeof(BoolMarshaller))] 103 | internal static unsafe class BoolMarshaller 104 | { 105 | public static byte ConvertToUnmanaged(bool managed) 106 | => (byte)(managed ? 1 : 0); 107 | 108 | public static bool ConvertToManaged(byte unmanaged) 109 | => unmanaged != 0; 110 | } 111 | 112 | public class DllImportBoolMarshaler : ICustomMarshaler 113 | { 114 | public static ICustomMarshaler GetInstance(string str) 115 | { 116 | return new DllImportBoolMarshaler(); 117 | } 118 | 119 | public void CleanUpManagedData(object ManagedObj) 120 | { 121 | 122 | } 123 | 124 | public void CleanUpNativeData(IntPtr pNativeData) 125 | { 126 | 127 | } 128 | 129 | public int GetNativeDataSize() 130 | { 131 | return 1; 132 | } 133 | 134 | public IntPtr MarshalManagedToNative(object ManagedObj) 135 | { 136 | return IntPtr.Zero; 137 | } 138 | 139 | public object MarshalNativeToManaged(IntPtr pNativeData) 140 | { 141 | return ((byte) pNativeData) != 0 ? "True" : "False"; 142 | } 143 | } 144 | 145 | public struct MyData 146 | { 147 | public int field1; 148 | public short field2; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /managed/managed.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 0.0.0.0 6 | false 7 | false 8 | true 9 | true 10 | 11 | true 12 | $(BaseIntermediateOutputPath)/SourceGenerated 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /managed/managed.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34525.116 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "managed", "managed.csproj", "{25275C5F-4C92-46D8-945B-A3B5844FEBC6}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {25275C5F-4C92-46D8-945B-A3B5844FEBC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {25275C5F-4C92-46D8-945B-A3B5844FEBC6}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {25275C5F-4C92-46D8-945B-A3B5844FEBC6}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {25275C5F-4C92-46D8-945B-A3B5844FEBC6}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {882FE85B-75D8-4AA2-89AA-B420E8795A55} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /native/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(csharpify_native) 2 | set(CMAKE_CXX_STANDARD 17) 3 | set(CMAKE_C_STANDARD 17) 4 | 5 | set(CSHARPIFY_NAME "${CMAKE_EXECUTABLE_PREFIX}csharpify") 6 | set(CSHARPIFY_FILE "${CSHARPIFY_NAME}${CMAKE_EXECUTABLE_SUFFIX}") 7 | 8 | cmake_path(APPEND CMAKE_SOURCE_DIR "imgui" OUTPUT_VARIABLE IMGUI_DIR) 9 | cmake_path(APPEND CMAKE_SOURCE_DIR "cimgui" OUTPUT_VARIABLE CIMGUI_DIR) 10 | 11 | file(READ ${IMGUI_DIR}/examples/example_sdl2_vulkan/main.cpp IMGUI_GEN) 12 | string(LENGTH "${IMGUI_GEN}" IMGUI_GEN_LEN) 13 | string(FIND "${IMGUI_GEN}" "ImGui::NewFrame();" startpos REVERSE) 14 | string(FIND "${IMGUI_GEN}" "ImGui::Render();" endpos REVERSE) 15 | string(SUBSTRING "${IMGUI_GEN}" 0 ${startpos} IMGUI_GEN_HEADER) 16 | string(SUBSTRING "${IMGUI_GEN}" ${endpos} ${IMGUI_GEN_LEN} IMGUI_GEN_FOOTER) 17 | string(JOIN "ImGui::NewFrame();\nMainLoop();\n" IMGUI_GEN "${IMGUI_GEN_HEADER}" "${IMGUI_GEN_FOOTER}") 18 | string(PREPEND IMGUI_GEN "#include \"imgui_bridge.h\"\n") 19 | string(REPLACE "int main(int" "int imgui_main(int" IMGUI_GEN "${IMGUI_GEN}") 20 | file(WRITE ${PROJECT_BINARY_DIR}/imgui.gen.cpp "${IMGUI_GEN}") 21 | 22 | file(READ ${CIMGUI_DIR}/cimgui.cpp CIMGUI_GEN) 23 | string(LENGTH "${CIMGUI_GEN}" CIMGUI_GEN_LEN) 24 | string(REPLACE "#include \"./imgui/" "#include \"" CIMGUI_GEN "${CIMGUI_GEN}") 25 | file(WRITE ${PROJECT_BINARY_DIR}/cimgui.gen.cpp "${CIMGUI_GEN}") 26 | 27 | set(DOTNET_LIBS "") 28 | 29 | if(DOTNET_RUNTIME STREQUAL "coreclr") 30 | set(DOTNET_LIBS 31 | coreclr 32 | ) 33 | endif() 34 | 35 | if(DOTNET_PLATFORM STREQUAL "win") 36 | list(APPEND coreclr_shared_sources 37 | coreclr/coreclr_win.cpp) 38 | else() 39 | list(APPEND coreclr_shared_sources 40 | coreclr/coreclr.cpp) 41 | endif() 42 | 43 | list(APPEND mono_shared_sources 44 | mono/mono.cpp 45 | ) 46 | 47 | list(APPEND csharpify_sources 48 | main.cpp 49 | ${generated_INCLUDE_DIR}/exports.g.c 50 | ${PROJECT_BINARY_DIR}/imgui.gen.cpp 51 | ${IMGUI_DIR}/imgui.cpp 52 | ${IMGUI_DIR}/imgui_demo.cpp 53 | ${IMGUI_DIR}/imgui_draw.cpp 54 | ${IMGUI_DIR}/imgui_tables.cpp 55 | ${IMGUI_DIR}/imgui_widgets.cpp 56 | ${IMGUI_DIR}/backends/imgui_impl_sdl2.cpp 57 | ${IMGUI_DIR}/backends/imgui_impl_vulkan.cpp 58 | ${PROJECT_BINARY_DIR}/cimgui.gen.cpp 59 | ) 60 | 61 | configure_file(config.h.in include/config.h) 62 | 63 | add_library(csharpify_coreclr INTERFACE) 64 | add_library(csharpify_mono INTERFACE) 65 | 66 | add_executable(csharpify ${csharpify_sources}) 67 | 68 | if(RUNTIME_CORECLR) 69 | target_link_libraries(csharpify csharpify_coreclr) 70 | elseif(RUNTIME_MONO) 71 | target_link_libraries(csharpify csharpify_mono) 72 | elseif(RUNTIME_NATIVEAOT) 73 | endif() 74 | 75 | add_dependencies(csharpify packages) 76 | 77 | if(BUILD_SDL2) 78 | target_link_libraries(csharpify SDL2-static) 79 | add_dependencies(csharpify SDL2-static) 80 | else() 81 | target_link_libraries(csharpify ${SDL2_LIBRARIES}) 82 | endif() 83 | 84 | 85 | list(APPEND headers_base_dirs 86 | include 87 | ${SHARED_INCLUDE_DIRS} 88 | ) 89 | 90 | list(APPEND headers_shared 91 | include/common.h 92 | include/managed_exports.h 93 | include/managed_bridge.h 94 | include/utils.h 95 | include/coreclrhost.h 96 | ${SHARED_HEADERS} 97 | ) 98 | 99 | target_sources(csharpify 100 | PRIVATE FILE_SET HEADERS 101 | BASE_DIRS ${headers_base_dirs} "${PROJECT_BINARY_DIR}/include" "${generated_INCLUDE_DIR}" 102 | FILES 103 | ${headers_shared} 104 | include/imgui_bridge.h 105 | include/main.h 106 | "${PROJECT_BINARY_DIR}/include/config.h" 107 | "${generated_INCLUDE_DIR}/dnne.h" 108 | "${generated_INCLUDE_DIR}/exports.h" 109 | ) 110 | 111 | target_sources(csharpify_coreclr INTERFACE 112 | FILE_SET HEADERS 113 | BASE_DIRS ${headers_base_dirs} coreclr 114 | FILES 115 | ${headers_shared} 116 | coreclr/bridge.h 117 | coreclr/runtime.h 118 | ) 119 | 120 | target_sources(csharpify_mono INTERFACE 121 | FILE_SET HEADERS 122 | BASE_DIRS ${headers_base_dirs} mono 123 | FILES 124 | ${headers_shared} 125 | mono/bridge.h 126 | mono/runtime.h 127 | ) 128 | 129 | foreach(thing ${coreclr_shared_sources}) 130 | list(APPEND coreclr_export_sources 131 | "$" 132 | "$" 133 | ) 134 | endforeach() 135 | 136 | foreach(thing ${mono_shared_sources}) 137 | list(APPEND mono_export_sources 138 | "$" 139 | "$" 140 | ) 141 | endforeach() 142 | 143 | target_sources(csharpify_coreclr INTERFACE ${coreclr_export_sources}) 144 | target_sources(csharpify_mono INTERFACE ${mono_export_sources}) 145 | 146 | if(RUNTIME_CORECLR) 147 | target_sources(csharpify 148 | PRIVATE FILE_SET HEADERS 149 | BASE_DIRS coreclr 150 | FILES 151 | coreclr/bridge.h 152 | coreclr/runtime.h 153 | ) 154 | else(RUNTIME_MONO) 155 | target_sources(csharpify 156 | PRIVATE FILE_SET HEADERS 157 | BASE_DIRS mono 158 | FILES 159 | mono/bridge.h 160 | mono/runtime.h 161 | ) 162 | endif() 163 | 164 | target_include_directories(csharpify PRIVATE 165 | ${DOTNET_INCLUDE_DIRS} 166 | ${generated_INCLUDE_DIR} 167 | ${SDL2_INCLUDE_DIRS} 168 | ${Vulkan_INCLUDE_DIRS} 169 | "${IMGUI_DIR}" 170 | "${IMGUI_DIR}/backends" 171 | "${CMAKE_SOURCE_DIR}/cimgui" 172 | ) 173 | 174 | if(BUILD_SDL2) 175 | target_include_directories(csharpify PRIVATE 176 | "$" 177 | "$" 178 | "$>/SDL2>" 179 | "$" 180 | "$" 181 | ) 182 | else() 183 | target_include_directories(csharpify PRIVATE 184 | ${SDL2_INCLUDE_DIRS} 185 | ) 186 | 187 | endif() 188 | 189 | target_link_libraries(csharpify 190 | ${Vulkan_LIBRARY} 191 | ) 192 | 193 | if(USE_MOLTENVK) 194 | target_link_libraries(csharpify 195 | ${Vulkan_MoltenVK_LIBRARY} 196 | ) 197 | endif() 198 | 199 | if(DOTNET_PLATFORM STREQUAL "osx") 200 | target_link_libraries(csharpify 201 | ${IOKIT} 202 | ) 203 | endif() 204 | 205 | if(CORECLR) 206 | target_link_libraries(csharpify ${CORECLR}) 207 | endif() 208 | 209 | target_compile_definitions(csharpify PRIVATE DNNE_COMPILE_AS_SOURCE DNNE_SELF_CONTAINED_RUNTIME) 210 | 211 | link_directories(csharpify ${DOTNET_LIBRARY_PATH}) 212 | 213 | add_dependencies(csharpify csharpify_managed) 214 | 215 | if(NOT BUILD_SDL2) 216 | get_target_property(SDL2_DLL SDL2::SDL2 "IMPORTED_LOCATION") 217 | 218 | list(APPEND build_outputs 219 | "${SDL2_DLL}" 220 | ) 221 | endif() 222 | 223 | # Bundle everything into a runnable directory 224 | set(bundle_dir "${CMAKE_BINARY_DIR}/bin") 225 | 226 | foreach(thing ${build_outputs}) 227 | cmake_path(GET thing FILENAME filename) 228 | list(APPEND bundle_outputs "${bundle_dir}/${CMAKE_BUILD_TYPE}/${filename}") 229 | endforeach() 230 | 231 | list(APPEND bundle_outputs "${bundle_dir}/${CMAKE_BUILD_TYPE}/${CSHARPIFY_FILE}") 232 | 233 | add_custom_command( 234 | OUTPUT ${bundle_outputs} 235 | COMMAND ${CMAKE_COMMAND} -E make_directory "${bundle_dir}/$" 236 | COMMAND ${CMAKE_COMMAND} -E copy -t "${bundle_dir}/$" "$" ${build_outputs} 237 | DEPENDS ${build_outputs} "$" 238 | ) 239 | 240 | if(DOTNET_PLATFORM STREQUAL "win") 241 | list(APPEND symbols "$<$:${PROJECT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${CSHARPIFY_NAME}.pdb>") 242 | list(APPEND bundle_symbols "$<$:${bundle_dir}/${CMAKE_BUILD_TYPE}/${CSHARPIFY_NAME}.pdb>") 243 | 244 | add_custom_command( 245 | OUTPUT ${bundle_symbols} 246 | COMMAND ${CMAKE_COMMAND} -E copy -t "${bundle_dir}/$" ${symbols} 247 | DEPENDS ${symbols} 248 | ) 249 | endif() 250 | 251 | 252 | add_custom_target(csharpify_native_bundled DEPENDS ${bundle_outputs} ${bundle_symbols}) 253 | 254 | add_custom_target(run 255 | COMMAND "${bundle_dir}/$/${CSHARPIFY_FILE}" 256 | DEPENDS "${bundle_dir}/$/${CSHARPIFY_FILE}" 257 | ) 258 | 259 | set_property(TARGET csharpify PROPERTY VS_DEBUGGER_COMMAND "${bundle_dir}/$/${CSHARPIFY_FILE}") 260 | set_property(TARGET csharpify PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${bundle_dir}/$") 261 | 262 | add_custom_target(program ALL DEPENDS csharpify_managed_bundled csharpify_native_bundled) -------------------------------------------------------------------------------- /native/config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef CSHARPIFY_CONFIG_H__ 2 | #define CSHARPIFY_CONFIG_H__ 3 | 4 | #define ASSEMBLYNAME "@ASSEMBLYNAME@" 5 | 6 | #define RUNTIME_CORECLR @RUNTIME_CORECLR@ 7 | #define RUNTIME_MONO @RUNTIME_MONO@ 8 | #define RUNTIME_NATIVEAOT @RUNTIME_NATIVEAOT@ 9 | 10 | #include "common.h" 11 | 12 | static constexpr char_t runtime_identifier[] = CSH_STR("@RID@"); 13 | 14 | #endif -------------------------------------------------------------------------------- /native/coreclr/bridge.h: -------------------------------------------------------------------------------- 1 | #if RUNTIME_CORECLR 2 | 3 | #ifndef CSHARPIFY_CORECLR_BRIDGE_H_ 4 | #define CSHARPIFY_CORECLR_BRIDGE_H_ 5 | 6 | #include "runtime.h" 7 | #include "coreclrhost.h" 8 | 9 | #define LOG_CORECLR(...) 10 | //#define LOG_CORECLR(...) fprintf (__VA_ARGS__) 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | // Representation of a managed object in native code. In Mono,the MonoObjects 17 | // are tracked by the GC (which scans the stack), but we can't make CoreCLR 18 | // scan the stack, so we use a reference counted version of MonoObject instead - 19 | // - we just put the GCHandle into a reference counted MonoObject, and when the 20 | // MonoObject is freed, then we free the GCHandle as well. 21 | // 22 | // This struct must be kept in sync with the MonoObject struct in Runtime.CoreCLR.cs 23 | struct _MonoObject { 24 | uint32_t reference_count; 25 | GCHandle gchandle; 26 | // We write the value of the struct here every time we create a MonoObject instance. 27 | // We can also fetch this value when it's needed (as opposed to creating it every time), 28 | // but that runs into threading issues (what if two threads needs it at the same time?). 29 | // Nothing unsolvable, but I'm going with the simplest solution until this is proven 30 | // to be a problem. 31 | void* struct_value; 32 | }; 33 | 34 | // This struct must be kept in sync with the MonoMethodSignature struct in Runtime.CoreCLR.cs 35 | struct _MonoMethodSignature { 36 | MonoObject* method; 37 | int parameter_count; 38 | MonoObject* return_type; 39 | MonoObject* parameters[]; 40 | }; 41 | 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif // CSHARPIFY_CORECLR_BRIDGE_H_ 48 | #endif // CORECLR_RUNTIME -------------------------------------------------------------------------------- /native/coreclr/coreclr.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "common.h" 3 | 4 | #if RUNTIME_CORECLR && !PLATFORM_WIN 5 | #include "utils.h" 6 | 7 | #include "managed_exports.h" 8 | #include "bridge.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace fs = std::filesystem; 17 | 18 | static bool initialized; 19 | 20 | static void* coreclr_handle = nullptr; 21 | static unsigned int coreclr_domainId = 0; 22 | 23 | static void* load_symbol(void* handle, const std::string &name) { 24 | assert(!name.empty()); 25 | 26 | void* ret; 27 | if (!handle) { 28 | ret = dlsym(RTLD_SELF, name.c_str()); 29 | } else { 30 | ret = dlsym(handle, name.c_str()); 31 | } 32 | assert(ret != nullptr); 33 | return ret; 34 | } 35 | 36 | char* strdup_printf(int* len, const char* msg, ...) { 37 | // COOP: no managed memory access: any mode 38 | va_list args; 39 | char* formatted = nullptr; 40 | 41 | va_start (args, msg); 42 | *len = vasprintf(&formatted, msg, args); 43 | va_end (args); 44 | 45 | return formatted; 46 | } 47 | 48 | void* pinvoke_override(const char* libraryName, const char* entrypointName) { 49 | void* symbol = nullptr; 50 | if (!strcmp(libraryName, "__Internal") || 51 | !strcmp(libraryName, "cimgui")) { 52 | symbol = load_symbol(nullptr, entrypointName); 53 | } 54 | return symbol; 55 | } 56 | 57 | int load_managed_runtime() { 58 | fs::path assemblyPath = "."; 59 | auto assemblyName = ASSEMBLYNAME ".dll"; 60 | fs::path startAssembly = assemblyPath / assemblyName; 61 | 62 | auto basePath = normalizePath("."); 63 | 64 | auto runtimePath = fs::path{normalizePath("sdk")}; 65 | 66 | std::string paths; 67 | for (auto const &dir_entry: fs::directory_iterator{runtimePath}) { 68 | if (dir_entry.is_directory()) 69 | continue; 70 | 71 | if (dir_entry.path().extension() != ".dll") 72 | continue; 73 | 74 | if (dir_entry.path().stem() == ASSEMBLYNAME) 75 | continue; 76 | 77 | if (paths.empty()) 78 | paths = dir_entry.path().string(); 79 | else { 80 | paths += ":"; 81 | paths += dir_entry.path().string(); 82 | } 83 | } 84 | 85 | int len; 86 | char* pinvoke_override_ptr = strdup_printf(&len, "%p", &pinvoke_override); 87 | 88 | const char* propertyKeys[] = { 89 | HOST_PROPERTY_APP_CONTEXT_BASE_DIRECTORY, // path to where the managed assemblies are (usually at least - RID-specific assemblies will be in subfolders) 90 | HOST_PROPERTY_APP_PATHS, 91 | HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES, 92 | HOST_PROPERTY_RUNTIME_IDENTIFIER, 93 | HOST_PROPERTY_PINVOKE_OVERRIDE 94 | }; 95 | 96 | const char* propertyValues[] = { 97 | basePath.c_str(), 98 | basePath.c_str(), 99 | paths.c_str(), 100 | runtime_identifier, 101 | pinvoke_override_ptr, 102 | }; 103 | 104 | int rv = coreclr_initialize( 105 | basePath.c_str(), 106 | ASSEMBLYNAME, 107 | sizeof(propertyKeys) / sizeof(char*), 108 | propertyKeys, 109 | propertyValues, 110 | &coreclr_handle, 111 | &coreclr_domainId 112 | ); 113 | 114 | initialized = true; 115 | return rv; 116 | } 117 | 118 | CSHARPIFY_BEGIN_C 119 | void* get_fast_callable_managed_function( 120 | const char_t* dotnet_type, 121 | const char_t* dotnet_type_method) { 122 | 123 | if (!initialized) { 124 | load_managed_runtime(); 125 | } 126 | 127 | std::string typeAndAssembly{dotnet_type}; 128 | auto pos = typeAndAssembly.find(", "); 129 | std::string type = typeAndAssembly.substr(0, pos); 130 | std::string assembly = typeAndAssembly.substr(pos + 2); 131 | 132 | void* del = nullptr; 133 | int rv = coreclr_create_delegate(coreclr_handle, coreclr_domainId, assembly.c_str(), type.c_str(), 134 | dotnet_type_method, &del); 135 | return del; 136 | } 137 | 138 | CSHARPIFY_END_C 139 | 140 | int register_icall(const char* name, const void* fnptr) { 141 | return 0; 142 | } 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /native/coreclr/coreclr_win.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "common.h" 3 | 4 | #if RUNTIME_CORECLR && PLATFORM_WIN 5 | 6 | #define WIN32_LEAN_AND_MEAN 7 | #define NOMINMAX 8 | 9 | #include "managed_exports.h" 10 | #include "bridge.h" 11 | #include "utils.h" 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #define CSH_LOCK_OPEN (0) 24 | #define CSH_LOCK_TAKEN (-1) 25 | 26 | #define CSH_MAX_PATH 512 27 | #define CSH_NORETURN __declspec(noreturn) 28 | 29 | namespace fs = std::filesystem; 30 | using lock_handle = volatile long; 31 | 32 | namespace { 33 | failure_fn failure_fptr; 34 | lock_handle prepare_lock = CSH_LOCK_OPEN; 35 | 36 | bool initialized; 37 | 38 | hostfxr_initialize_for_dotnet_command_line_fn init_self_contained_fptr; 39 | hostfxr_initialize_for_runtime_config_fn init_fptr; 40 | hostfxr_get_runtime_delegate_fn get_delegate_fptr; 41 | hostfxr_close_fn close_fptr; 42 | hostfxr_set_runtime_property_value_fn set_runtime_property_value_fptr; 43 | 44 | load_assembly_and_get_function_pointer_ptr load_assembly_and_get_function_pointer_fptr; 45 | coreclr_create_delegate_ptr coreclr_create_delegate_fptr; 46 | 47 | std::wstring assemblyPath; 48 | } 49 | 50 | CSH_EXTERN_C CSH_EXPORT_API void CSH_CALLTYPE set_failure_callback(failure_fn cb) 51 | { 52 | failure_fptr = cb; 53 | } 54 | 55 | CSH_NORETURN static void noreturn_failure(enum failure_type type, int error_code) 56 | { 57 | if (failure_fptr) 58 | failure_fptr(type, error_code); 59 | 60 | // Don't trust anything the user can override. 61 | abort(); 62 | } 63 | 64 | #define IF_FAILURE_RETURN_OR_ABORT(type, rc, lock) \ 65 | { \ 66 | if (is_failure(rc)) \ 67 | { \ 68 | exit_lock(lock); \ 69 | noreturn_failure(type, rc); \ 70 | } \ 71 | } 72 | 73 | void enter_lock(lock_handle *lock) 74 | { 75 | while (InterlockedCompareExchange(lock, -1, CSH_LOCK_OPEN) != CSH_LOCK_TAKEN) { 76 | Sleep(1 /* milliseconds */); 77 | } 78 | } 79 | 80 | void exit_lock(lock_handle *lock) 81 | { 82 | InterlockedExchange(lock, CSH_LOCK_OPEN); 83 | } 84 | 85 | bool is_failure(int rc) 86 | { 87 | // The CLR hosting API uses the Win32 HRESULT scheme. This means 88 | // the high order bit indicates an error and S_FALSE (1) can be returned 89 | // and is _not_ a failure. 90 | return rc < 0; 91 | } 92 | 93 | int get_current_error() 94 | { 95 | return static_cast(GetLastError()); 96 | } 97 | 98 | void set_current_error(const int err) 99 | { 100 | SetLastError(static_cast(err)); 101 | } 102 | 103 | 104 | void *load_library(const std::wstring &path) 105 | { 106 | assert(!path.empty()); 107 | HMODULE h = LoadLibraryW(path.c_str()); 108 | assert(h != NULL); 109 | return h; 110 | } 111 | 112 | void *load_symbol(void *h, const std::string &name) 113 | { 114 | assert(!name.empty()); 115 | 116 | if (!h) { 117 | h = GetModuleHandle(nullptr); 118 | } 119 | void *f = GetProcAddress(static_cast(h), name.c_str()); 120 | assert(f != nullptr); 121 | return f; 122 | } 123 | 124 | /* 125 | * vscprintf: 126 | * MSVC implements this as _vscprintf, thus we just 'symlink' it here 127 | * GNU-C-compatible compilers do not implement this, thus we implement it here 128 | */ 129 | #ifdef _MSC_VER 130 | #define vscprintf _vscprintf 131 | #endif 132 | 133 | #ifdef __GNUC__ 134 | int vscprintf(const char *format, va_list ap) 135 | { 136 | va_list ap_copy; 137 | va_copy(ap_copy, ap); 138 | int retval = vsnprintf(NULL, 0, format, ap_copy); 139 | va_end(ap_copy); 140 | return retval; 141 | } 142 | #endif 143 | 144 | #ifdef _MSC_VER 145 | int vasprintf(char **strp, const char *format, va_list ap) 146 | { 147 | const int len = vscprintf(format, ap); 148 | if (len == -1) 149 | return -1; 150 | auto str = static_cast(malloc(static_cast(len) + 1)); 151 | if (!str) 152 | return -1; 153 | const int retval = vsnprintf(str, len + 1, format, ap); 154 | if (retval == -1) { 155 | free(str); 156 | return -1; 157 | } 158 | *strp = str; 159 | return retval; 160 | } 161 | #endif 162 | 163 | char_t *copy(WSTRING str) 164 | { 165 | const auto ret = new char_t[str.size() + 1]; 166 | std::copy(str.begin(), str.end(), ret); 167 | ret[str.size()] = L'\0'; 168 | return ret; 169 | } 170 | 171 | char *strdup_printf(int *len, const char *msg, ...) 172 | { 173 | // COOP: no managed memory access: any mode 174 | va_list args; 175 | char *formatted = nullptr; 176 | 177 | va_start(args, msg); 178 | *len = vasprintf(&formatted, msg, args); 179 | va_end(args); 180 | 181 | return formatted; 182 | } 183 | 184 | void *pinvoke_override(const char *libraryName, const char *entrypointName) 185 | { 186 | void *symbol = nullptr; 187 | if (!strcmp(libraryName, "__Internal") || 188 | !strcmp(libraryName, "SDL2") || 189 | !strcmp(libraryName, "cimgui")) { 190 | symbol = load_symbol(nullptr, entrypointName); 191 | } 192 | return symbol; 193 | } 194 | 195 | int load_hostfxr() 196 | { 197 | const auto path = fs::path(assemblyPath).parent_path().append("shared/host/fxr/hostfxr.dll"); 198 | 199 | // Load hostfxr and get desired exports. 200 | void *lib = load_library(path); 201 | 202 | init_self_contained_fptr = (hostfxr_initialize_for_dotnet_command_line_fn)load_symbol(lib, "hostfxr_initialize_for_dotnet_command_line"); 203 | init_fptr = (hostfxr_initialize_for_runtime_config_fn)load_symbol(lib, "hostfxr_initialize_for_runtime_config"); 204 | get_delegate_fptr = (hostfxr_get_runtime_delegate_fn)load_symbol(lib, "hostfxr_get_runtime_delegate"); 205 | close_fptr = (hostfxr_close_fn)load_symbol(lib, "hostfxr_close"); 206 | set_runtime_property_value_fptr = (hostfxr_set_runtime_property_value_fn)load_symbol(lib, "hostfxr_set_runtime_property_value"); 207 | 208 | assert(init_self_contained_fptr && init_fptr && get_delegate_fptr && close_fptr); 209 | return 0; 210 | } 211 | 212 | int init_dotnet() 213 | { 214 | // Self-contained scenario support relies upon the application scenario 215 | // entry-point. The logic here is to trick the hosting API into initializing as an application 216 | // but call the "load assembly and get delegate" instead of "run main". This has impact 217 | // on the TPA make-up and hence assembly loading in general since the TPA populates the default ALC. 218 | const char_t *configPath = assemblyPath.c_str(); 219 | 220 | // Load .NET runtime 221 | hostfxr_handle ctx = nullptr; 222 | int rc = init_self_contained_fptr(1, &configPath, nullptr, &ctx); 223 | if (is_failure(rc)) { 224 | close_fptr(ctx); 225 | return rc; 226 | } 227 | 228 | int len; 229 | const char* strptr = strdup_printf(&len, "0x%pZ", &pinvoke_override); 230 | const char_t* pinvoke = StringToUnicode(strptr, len); 231 | set_runtime_property_value_fptr(ctx, CSH_STR("PINVOKE_OVERRIDE"), pinvoke); 232 | 233 | void* ptr; 234 | // Get the load assembly function pointer 235 | rc = get_delegate_fptr(ctx, hdt_load_assembly_and_get_function_pointer, &ptr); 236 | if (is_failure(rc)) { 237 | close_fptr(ctx); 238 | return rc; 239 | } 240 | 241 | load_assembly_and_get_function_pointer_fptr = (load_assembly_and_get_function_pointer_ptr)ptr; 242 | return DNNE_SUCCESS; 243 | } 244 | 245 | int load_managed_runtime() 246 | { 247 | // Lock and check if the needed export was already acquired. 248 | enter_lock(&prepare_lock); 249 | if (!initialized) { 250 | const auto assemblyName = ASSEMBLYNAME ".dll"; 251 | fs::path startAssembly = fs::path(".") / assemblyName; 252 | assemblyPath = normalizePathW(startAssembly); 253 | 254 | // Load HostFxr and get exported hosting functions. 255 | int rc = load_hostfxr(); 256 | IF_FAILURE_RETURN_OR_ABORT(failure_load_runtime, rc, &prepare_lock); 257 | 258 | // Initialize and start the runtime. 259 | rc = init_dotnet(); 260 | IF_FAILURE_RETURN_OR_ABORT(failure_load_runtime, rc, &prepare_lock); 261 | 262 | assert(load_assembly_and_get_function_pointer_fptr != nullptr); 263 | initialized = true; 264 | } 265 | exit_lock(&prepare_lock); 266 | 267 | return 0; 268 | } 269 | 270 | int register_icall(const char *name, const void *fnptr) 271 | { 272 | return 0; 273 | } 274 | 275 | void *get_callable_managed_function(const char_t *dotnetType, const char_t *dotnetTypeMethod, 276 | const char_t *dotnetDelegateType) 277 | { 278 | assert(dotnetType && dotnetTypeMethod); 279 | 280 | // Store the current error state to reset it when 281 | // we exit this function. This being done because this 282 | // API is an implementation detail of the export but 283 | // can result in side-effects during export resolution. 284 | const int currError = get_current_error(); 285 | int rc; 286 | // Check if the runtime has already been prepared. 287 | if (!initialized) { 288 | rc = load_managed_runtime(); 289 | if (is_failure(rc)) { 290 | noreturn_failure(failure_load_export, rc); 291 | } 292 | } 293 | 294 | // Function pointer to managed function 295 | void *func = nullptr; 296 | rc = load_assembly_and_get_function_pointer_fptr( 297 | assemblyPath.c_str(), 298 | dotnetType, 299 | dotnetTypeMethod, 300 | dotnetDelegateType, 301 | nullptr, 302 | &func); 303 | 304 | if (is_failure(rc)) 305 | noreturn_failure(failure_load_export, rc); 306 | 307 | // Now that the export has been resolved, reset 308 | // the error state to hide this implementation detail. 309 | set_current_error(currError); 310 | return func; 311 | } 312 | 313 | CSH_EXTERN_C 314 | void *get_fast_callable_managed_function(const char_t *dotnetType,const char_t *dotnetTypeMethod) 315 | { 316 | return get_callable_managed_function(dotnetType, dotnetTypeMethod, (const char_t *)-1); 317 | } 318 | #endif 319 | -------------------------------------------------------------------------------- /native/coreclr/runtime.h: -------------------------------------------------------------------------------- 1 | #ifndef CSHARPIFY_CORECLR_RUNTIME_H_ 2 | #define CSHARPIFY_CORECLR_RUNTIME_H_ 3 | 4 | #ifdef _WIN32 5 | #define ssize_t long long 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | typedef void* GCHandle; 17 | 18 | /* This is copied from eglib's header files */ 19 | typedef unsigned int guint; 20 | typedef int32_t gboolean; 21 | typedef int32_t gint32; 22 | typedef uint32_t guint32; 23 | typedef char gchar; 24 | typedef void * gpointer; 25 | typedef const void * gconstpointer; 26 | typedef guint (*GHashFunc) (gconstpointer key); 27 | typedef gboolean (*GEqualFunc) (gconstpointer a, gconstpointer b); 28 | 29 | #ifndef GPOINTER_TO_UINT 30 | #define GPOINTER_TO_UINT(p) ((uint32_t) (long) (p)) 31 | #endif 32 | 33 | #ifndef GINT_TO_POINTER 34 | #define GINT_TO_POINTER(i) ((void *) (long) (i)) 35 | #endif 36 | 37 | 38 | /* mini/mono-private-unstable.h */ 39 | 40 | 41 | 42 | 43 | // static MonoCoreRuntimeProperties monovm_core_properties; 44 | 45 | /* This is copied from mono's header files */ 46 | 47 | /* utils/mono-publib.h */ 48 | #define MONO_API 49 | typedef int32_t mono_bool; 50 | 51 | /* metadata/image.h */ 52 | #if defined (CORECLR_RUNTIME) 53 | // In Mono, MonoAssembly is not related to MonoObject, but for the CoreCLR bridge we use the same memory representation for both types. 54 | typedef struct _MonoObject MonoAssembly; 55 | #else 56 | typedef struct _MonoAssembly MonoAssembly; 57 | #endif 58 | typedef struct _MonoAssemblyName MonoAssemblyName; 59 | typedef struct _MonoImage MonoImage; 60 | 61 | typedef enum { 62 | MONO_IMAGE_OK, 63 | MONO_IMAGE_ERROR_ERRNO, 64 | MONO_IMAGE_MISSING_ASSEMBLYREF, 65 | MONO_IMAGE_IMAGE_INVALID 66 | } MonoImageOpenStatus; 67 | 68 | /* metadata/metadata.h */ 69 | #if defined (CORECLR_RUNTIME) 70 | // In Mono, MonoClass is not related to MonoObject at all, but for the CoreCLR bridge we use the same struct representation for both types. 71 | typedef struct _MonoObject MonoClass; 72 | #else 73 | typedef struct _MonoClass MonoClass; 74 | #endif 75 | typedef struct _MonoDomain MonoDomain; 76 | #if defined (CORECLR_RUNTIME) 77 | // In Mono, MonoMethod is not related to MonoObject at all, but for the CoreCLR bridge we use the same struct representation for both types. 78 | typedef struct _MonoObject MonoMethod; 79 | #else 80 | typedef struct _MonoMethod MonoMethod; 81 | #endif 82 | typedef struct _MonoMethodSignature MonoMethodSignature; 83 | #if defined (CORECLR_RUNTIME) 84 | // In Mono, MonoType is not related to MonoObject at all, but for the CoreCLR bridge we use the same struct representation for both types. 85 | typedef struct _MonoObject MonoType; 86 | #else 87 | typedef struct _MonoType MonoType; 88 | #endif 89 | 90 | /* metadata/class.h */ 91 | typedef struct MonoVTable MonoVTable; 92 | 93 | typedef struct _MonoClassField MonoClassField; 94 | 95 | /* metadata/object.h */ 96 | #if defined (CORECLR_RUNTIME) 97 | // In Mono, these types are substructs of MonoObject, but for the CoreCLR bridge we use the same struct representation for both types. 98 | typedef struct _MonoObject MonoString; 99 | typedef struct _MonoObject MonoArray; 100 | typedef struct _MonoObject MonoReflectionAssembly; 101 | typedef struct _MonoObject MonoReflectionMethod; 102 | typedef struct _MonoObject MonoReflectionType; 103 | typedef struct _MonoObject MonoException; 104 | #else 105 | typedef struct _MonoString MonoString; 106 | typedef struct _MonoArray MonoArray; 107 | typedef struct _MonoReflectionAssembly MonoReflectionAssembly; 108 | typedef struct _MonoReflectionMethod MonoReflectionMethod; 109 | typedef struct _MonoReflectionType MonoReflectionType; 110 | typedef struct _MonoException MonoException; 111 | #endif 112 | typedef struct _MonoThread MonoThread; 113 | typedef struct _MonoThreadsSync MonoThreadsSync; 114 | typedef struct _MonoObject MonoObject; 115 | 116 | #if defined (CORECLR_RUNTIME) 117 | // In Mono, MonoReferenceQueue is not related to MonoObject at all, but for the CoreCLR bridge we use the same struct representation for both types. 118 | typedef struct _MonoObject MonoReferenceQueue; 119 | #else 120 | typedef struct _MonoReferenceQueue MonoReferenceQueue; 121 | #endif 122 | typedef void (*mono_reference_queue_callback) (void *user_data); 123 | 124 | #if !defined (CORECLR_RUNTIME) 125 | #define mono_array_addr(array,type,index) ((type*)(void*) mono_array_addr_with_size (array, sizeof (type), index)) 126 | #define mono_array_get(array,type,index) ( *(type*)mono_array_addr ((array), type, (index)) ) 127 | #define mono_array_setref(array,index,value,exception_gchandle) \ 128 | do { \ 129 | void **__p = (void **) mono_array_addr ((array), void*, (index)); \ 130 | mono_gc_wbarrier_set_arrayref ((array), __p, (MonoObject*)(value)); \ 131 | /* *__p = (value);*/ \ 132 | } while (0) 133 | #endif // !defined (CORECLR_RUNTIME) 134 | 135 | /* metadata/assembly.h */ 136 | 137 | typedef MonoAssembly * (*MonoAssemblyPreLoadFunc) (MonoAssemblyName *aname, char **assemblies_path, void* user_data); 138 | 139 | /* metadata/profiler.h */ 140 | typedef struct _MonoProfiler MonoProfiler; 141 | 142 | typedef enum { 143 | MONO_PROFILE_NONE = 0, 144 | MONO_PROFILE_APPDOMAIN_EVENTS = 1 << 0, 145 | MONO_PROFILE_ASSEMBLY_EVENTS = 1 << 1, 146 | MONO_PROFILE_MODULE_EVENTS = 1 << 2, 147 | MONO_PROFILE_CLASS_EVENTS = 1 << 3, 148 | MONO_PROFILE_JIT_COMPILATION = 1 << 4, 149 | MONO_PROFILE_INLINING = 1 << 5, 150 | MONO_PROFILE_EXCEPTIONS = 1 << 6, 151 | MONO_PROFILE_ALLOCATIONS = 1 << 7, 152 | MONO_PROFILE_GC = 1 << 8, 153 | MONO_PROFILE_THREADS = 1 << 9, 154 | MONO_PROFILE_REMOTING = 1 << 10, 155 | MONO_PROFILE_TRANSITIONS = 1 << 11, 156 | MONO_PROFILE_ENTER_LEAVE = 1 << 12, 157 | MONO_PROFILE_COVERAGE = 1 << 13, 158 | MONO_PROFILE_INS_COVERAGE = 1 << 14, 159 | MONO_PROFILE_STATISTICAL = 1 << 15, 160 | MONO_PROFILE_METHOD_EVENTS = 1 << 16, 161 | MONO_PROFILE_MONITOR_EVENTS = 1 << 17, 162 | MONO_PROFILE_IOMAP_EVENTS = 1 << 18, /* this should likely be removed, too */ 163 | MONO_PROFILE_GC_MOVES = 1 << 19, 164 | MONO_PROFILE_GC_ROOTS = 1 << 20 165 | } MonoProfileFlags; 166 | 167 | typedef enum { 168 | MONO_GC_EVENT_START, 169 | MONO_GC_EVENT_MARK_START, 170 | MONO_GC_EVENT_MARK_END, 171 | MONO_GC_EVENT_RECLAIM_START, 172 | MONO_GC_EVENT_RECLAIM_END, 173 | MONO_GC_EVENT_END, 174 | MONO_GC_EVENT_PRE_STOP_WORLD, 175 | MONO_GC_EVENT_POST_STOP_WORLD, 176 | MONO_GC_EVENT_PRE_START_WORLD, 177 | MONO_GC_EVENT_POST_START_WORLD 178 | } MonoGCEvent; 179 | 180 | typedef void (*MonoProfileFunc) (MonoProfiler *prof); 181 | typedef void (*MonoProfileThreadFunc) (MonoProfiler *prof, uintptr_t tid); 182 | typedef void (*MonoProfileGCFunc) (MonoProfiler *prof, MonoGCEvent event, int generation); 183 | typedef void (*MonoProfileGCResizeFunc) (MonoProfiler *prof, int64_t new_size); 184 | 185 | /* metadata/mono-debug.h */ 186 | 187 | typedef enum { 188 | MONO_DEBUG_FORMAT_NONE, 189 | MONO_DEBUG_FORMAT_MONO, 190 | /* Deprecated, the mdb debugger is not longer supported. */ 191 | MONO_DEBUG_FORMAT_DEBUGGER 192 | } MonoDebugFormat; 193 | 194 | /* mini/debugger-agent.h */ 195 | 196 | typedef struct { 197 | const char *name; 198 | void (*connect) (const char *address); 199 | void (*close1) (void); 200 | void (*close2) (void); 201 | gboolean (*send) (void *buf, size_t len); 202 | ssize_t (*recv) (void *buf, size_t len); 203 | } DebuggerTransport; 204 | 205 | /* metadata/mini.h */ 206 | typedef gboolean (*MonoExceptionFrameWalk) (MonoMethod *method, gpointer ip, size_t native_offset, gboolean managed, gpointer user_data); 207 | typedef void (*MonoUnhandledExceptionFunc) (MonoObject *exc, gpointer user_data); 208 | 209 | typedef unsigned char* (*MonoLoadAotDataFunc) (MonoAssembly *assembly, int size, gpointer user_data, void **out_handle); 210 | typedef void (*MonoFreeAotDataFunc) (MonoAssembly *assembly, int size, gpointer user_data, void *handle); 211 | 212 | /* metadata/blob.h */ 213 | 214 | /* 215 | * Encoding for type signatures used in the Metadata 216 | */ 217 | typedef enum { 218 | MONO_TYPE_END = 0x00, /* End of List */ 219 | MONO_TYPE_VOID = 0x01, 220 | MONO_TYPE_BOOLEAN = 0x02, 221 | MONO_TYPE_CHAR = 0x03, 222 | MONO_TYPE_I1 = 0x04, 223 | MONO_TYPE_U1 = 0x05, 224 | MONO_TYPE_I2 = 0x06, 225 | MONO_TYPE_U2 = 0x07, 226 | MONO_TYPE_I4 = 0x08, 227 | MONO_TYPE_U4 = 0x09, 228 | MONO_TYPE_I8 = 0x0a, 229 | MONO_TYPE_U8 = 0x0b, 230 | MONO_TYPE_R4 = 0x0c, 231 | MONO_TYPE_R8 = 0x0d, 232 | MONO_TYPE_STRING = 0x0e, 233 | MONO_TYPE_PTR = 0x0f, /* arg: token */ 234 | MONO_TYPE_BYREF = 0x10, /* arg: token */ 235 | MONO_TYPE_VALUETYPE = 0x11, /* arg: token */ 236 | MONO_TYPE_CLASS = 0x12, /* arg: token */ 237 | MONO_TYPE_VAR = 0x13, /* number */ 238 | MONO_TYPE_ARRAY = 0x14, /* type, rank, boundsCount, bound1, loCount, lo1 */ 239 | MONO_TYPE_GENERICINST= 0x15, /* \x{2026} */ 240 | MONO_TYPE_TYPEDBYREF = 0x16, 241 | MONO_TYPE_I = 0x18, 242 | MONO_TYPE_U = 0x19, 243 | MONO_TYPE_FNPTR = 0x1b, /* arg: full method signature */ 244 | MONO_TYPE_OBJECT = 0x1c, 245 | MONO_TYPE_SZARRAY = 0x1d, /* 0-based one-dim-array */ 246 | MONO_TYPE_MVAR = 0x1e, /* number */ 247 | MONO_TYPE_CMOD_REQD = 0x1f, /* arg: typedef or typeref token */ 248 | MONO_TYPE_CMOD_OPT = 0x20, /* optional arg: typedef or typref token */ 249 | MONO_TYPE_INTERNAL = 0x21, /* CLR internal type */ 250 | 251 | MONO_TYPE_MODIFIER = 0x40, /* Or with the following types */ 252 | MONO_TYPE_SENTINEL = 0x41, /* Sentinel for varargs method signature */ 253 | MONO_TYPE_PINNED = 0x45, /* Local var that points to pinned object */ 254 | 255 | MONO_TYPE_ENUM = 0x55 /* an enumeration */ 256 | } MonoTypeEnum; 257 | 258 | /* 259 | * From internal headers 260 | */ 261 | 262 | /* metadata/gc-internal.h */ 263 | 264 | enum { 265 | MONO_GC_FINALIZER_EXTENSION_VERSION = 1, 266 | }; 267 | 268 | typedef struct { 269 | int version; 270 | gboolean (*is_class_finalization_aware) (MonoClass *klass); 271 | void (*object_queued_for_finalization) (MonoObject *object); 272 | } MonoGCFinalizerCallbacks; 273 | 274 | /* metadata/sgen-toggleref.h */ 275 | 276 | typedef enum { 277 | MONO_TOGGLE_REF_DROP, 278 | MONO_TOGGLE_REF_STRONG, 279 | MONO_TOGGLE_REF_WEAK 280 | } MonoToggleRefStatus; 281 | 282 | typedef MonoToggleRefStatus (*MonoToggleRefCallback) (MonoObject *obj); 283 | 284 | /* metadata/mono-hash.h */ 285 | 286 | typedef enum { 287 | MONO_HASH_KEY_GC = 1, 288 | MONO_HASH_VALUE_GC = 2, 289 | MONO_HASH_KEY_VALUE_GC = MONO_HASH_KEY_GC | MONO_HASH_VALUE_GC, 290 | } MonoGHashGCType; 291 | 292 | #if defined (CORECLR_RUNTIME) 293 | // In Mono, MonoGHashTable is not related to MonoObject, but for the CoreCLR bridge we use the same memory representation for both types. 294 | typedef struct _MonoObject MonoGHashTable; 295 | #else 296 | typedef struct _MonoGHashTable MonoGHashTable; 297 | #endif 298 | 299 | /* utils/mono-logger.h */ 300 | 301 | typedef void (*MonoLogCallback) (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data); 302 | typedef void (*MonoPrintCallback) (const char *string, mono_bool is_stdout); 303 | 304 | /* mini/jit.h */ 305 | typedef enum { 306 | MONO_AOT_MODE_NONE, 307 | MONO_AOT_MODE_NORMAL, 308 | MONO_AOT_MODE_HYBRID, 309 | MONO_AOT_MODE_FULL, 310 | MONO_AOT_MODE_LLVMONLY, 311 | MONO_AOT_MODE_INTERP, 312 | MONO_AOT_MODE_INTERP_LLVMONLY, 313 | MONO_AOT_MODE_LLVMONLY_INTERP, 314 | MONO_AOT_MODE_INTERP_ONLY, 315 | } MonoAotMode; 316 | 317 | /* metadata/marshal.h */ 318 | 319 | // The 'gchandle' parameter is defined as a 'guint32' in mono/mono's 2020-02 branch, and as a 'MonoGCHandle' (aka void*) in mono/mono's main branch. 320 | // Here we go with the latter (void*), because that's the future, and it should also be compatible with the 2020-02 branch. 321 | typedef void (*MonoFtnPtrEHCallback) (GCHandle gchandle); 322 | 323 | /* mini/mono-private-unstable.h */ 324 | typedef struct { 325 | uint32_t kind; // 0 = Path of runtimeconfig.blob, 1 = pointer to image data, >= 2 undefined 326 | union { 327 | struct { 328 | const char *path; 329 | } name; 330 | struct { 331 | const char *data; 332 | uint32_t data_len; 333 | } data; 334 | } runtimeconfig; 335 | } MonovmRuntimeConfigArguments; 336 | 337 | typedef void (*MonovmRuntimeConfigArgumentsCleanup) (MonovmRuntimeConfigArguments *args, void *user_data); 338 | 339 | /* not in any header */ 340 | 341 | void mono_gc_init_finalizer_thread (); 342 | 343 | #ifdef __cplusplus 344 | } 345 | #endif 346 | 347 | #endif // CSHARPIFY_CORECLR_RUNTIME_H_ -------------------------------------------------------------------------------- /native/csharpify.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34525.116 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csharpify", "..\build\coreclr\native\csharpify.vcxproj", "{EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csharpify_native_bundled", "..\build\coreclr\native\csharpify_native_bundled.vcxproj", "{62FB160A-67A2-36FF-911B-9B41FFED19CC}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "managed", "..\managed\managed.csproj", "{80C2E0D9-B011-4C9F-A914-D9F45D2F103E}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csharpify_managed_bundled", "..\build\coreclr\managed\csharpify_managed_bundled.vcxproj", "{22EF3589-480D-3641-9259-7633F03E4E4B}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Debug|x64 = Debug|x64 18 | MinSizeRel|Any CPU = MinSizeRel|Any CPU 19 | MinSizeRel|x64 = MinSizeRel|x64 20 | Release|Any CPU = Release|Any CPU 21 | Release|x64 = Release|x64 22 | RelWithDebInfo|Any CPU = RelWithDebInfo|Any CPU 23 | RelWithDebInfo|x64 = RelWithDebInfo|x64 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.Debug|Any CPU.ActiveCfg = Debug|x64 27 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.Debug|Any CPU.Build.0 = Debug|x64 28 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.Debug|x64.ActiveCfg = Debug|x64 29 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.Debug|x64.Build.0 = Debug|x64 30 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|x64 31 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|x64 32 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 33 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 34 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.Release|Any CPU.ActiveCfg = Release|x64 35 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.Release|Any CPU.Build.0 = Release|x64 36 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.Release|x64.ActiveCfg = Release|x64 37 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.Release|x64.Build.0 = Release|x64 38 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|x64 39 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|x64 40 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 41 | {EEC14BE9-9392-3A60-9BC4-F423EDDCBBCD}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 42 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.Debug|Any CPU.ActiveCfg = Debug|x64 43 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.Debug|Any CPU.Build.0 = Debug|x64 44 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.Debug|x64.ActiveCfg = Debug|x64 45 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.Debug|x64.Build.0 = Debug|x64 46 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|x64 47 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|x64 48 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 49 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 50 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.Release|Any CPU.ActiveCfg = Release|x64 51 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.Release|Any CPU.Build.0 = Release|x64 52 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.Release|x64.ActiveCfg = Release|x64 53 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.Release|x64.Build.0 = Release|x64 54 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|x64 55 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|x64 56 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 57 | {62FB160A-67A2-36FF-911B-9B41FFED19CC}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 58 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.Debug|x64.ActiveCfg = Debug|Any CPU 61 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.Debug|x64.Build.0 = Debug|Any CPU 62 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU 63 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU 64 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU 65 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.MinSizeRel|x64.Build.0 = Debug|Any CPU 66 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.Release|Any CPU.ActiveCfg = Release|Any CPU 67 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.Release|Any CPU.Build.0 = Release|Any CPU 68 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.Release|x64.ActiveCfg = Release|Any CPU 69 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.Release|x64.Build.0 = Release|Any CPU 70 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU 71 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU 72 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU 73 | {80C2E0D9-B011-4C9F-A914-D9F45D2F103E}.RelWithDebInfo|x64.Build.0 = Release|Any CPU 74 | {22EF3589-480D-3641-9259-7633F03E4E4B}.Debug|Any CPU.ActiveCfg = Debug|x64 75 | {22EF3589-480D-3641-9259-7633F03E4E4B}.Debug|Any CPU.Build.0 = Debug|x64 76 | {22EF3589-480D-3641-9259-7633F03E4E4B}.Debug|x64.ActiveCfg = Debug|x64 77 | {22EF3589-480D-3641-9259-7633F03E4E4B}.Debug|x64.Build.0 = Debug|x64 78 | {22EF3589-480D-3641-9259-7633F03E4E4B}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|x64 79 | {22EF3589-480D-3641-9259-7633F03E4E4B}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|x64 80 | {22EF3589-480D-3641-9259-7633F03E4E4B}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 81 | {22EF3589-480D-3641-9259-7633F03E4E4B}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 82 | {22EF3589-480D-3641-9259-7633F03E4E4B}.Release|Any CPU.ActiveCfg = Release|x64 83 | {22EF3589-480D-3641-9259-7633F03E4E4B}.Release|Any CPU.Build.0 = Release|x64 84 | {22EF3589-480D-3641-9259-7633F03E4E4B}.Release|x64.ActiveCfg = Release|x64 85 | {22EF3589-480D-3641-9259-7633F03E4E4B}.Release|x64.Build.0 = Release|x64 86 | {22EF3589-480D-3641-9259-7633F03E4E4B}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|x64 87 | {22EF3589-480D-3641-9259-7633F03E4E4B}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|x64 88 | {22EF3589-480D-3641-9259-7633F03E4E4B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 89 | {22EF3589-480D-3641-9259-7633F03E4E4B}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 90 | EndGlobalSection 91 | GlobalSection(SolutionProperties) = preSolution 92 | HideSolutionNode = FALSE 93 | EndGlobalSection 94 | GlobalSection(ExtensibilityGlobals) = postSolution 95 | SolutionGuid = {2C538C20-C304-32EF-B246-6B88773661E1} 96 | EndGlobalSection 97 | EndGlobal 98 | -------------------------------------------------------------------------------- /native/include/common.h: -------------------------------------------------------------------------------- 1 | #ifndef CSHARPIFY_COMMON_H 2 | #define CSHARPIFY_COMMON_H 3 | 4 | #if defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) 5 | # define COMPILER_MSVC 1 6 | #elif defined(__clang) 7 | # define COMPILER_CLANG 1 8 | #elif defined(__GNUC__) 9 | # define COMPILER_GNUC 1 10 | #endif 11 | 12 | #if !defined(PLATFORM_CONFIGURED) 13 | 14 | //#define PLATFORM_WIN 0 15 | //#define PLATFORM_LINUX 0 16 | //#define PLATFORM_MAC 0 17 | //#define PLATFORM_IOS 0 18 | //#define PLATFORM_TVOS 0 19 | //#define PLATFORM_WATCHOS 0 20 | //#define PLATFORM_VISIONOS 0 21 | //#define PLATFORM_ANDROID 0 22 | //#define PLATFORM_ARCH_32 0 23 | //#define PLATFORM_ARCH_64 0 24 | 25 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(__CYGWIN32__) 26 | # define PLATFORM_WIN 1 27 | #elif defined(__MACH__) || defined(__APPLE__) 28 | 29 | # include 30 | 31 | #if TARGET_OS_OSX == 1 32 | # define PLATFORM_MAC 1 33 | #else 34 | #if TARGET_OS_SIMULATOR == 1 35 | # define PLATFORM_IOS_SIMULATOR 1 36 | #endif 37 | 38 | #if TARGET_OS_MACCATALYST == 1 39 | # define PLATFORM_MACCATALYST 1 40 | #endif 41 | 42 | #if TARGET_OS_IOS == 1 43 | # define PLATFORM_IOS 1 44 | #elif TARGET_OS_TV == 1 45 | # define PLATFORM_TVOS 1 46 | #elif TARGET_OS_WATCH == 1 47 | # define PLATFORM_WATCHOS 1 48 | #elif TARGET_OS_VISION == 1 49 | # define PLATFORM_VISIONOS 1 50 | #endif 51 | #endif 52 | 53 | #elif defined(__ANDROID__) 54 | # define PLATFORM_ANDROID 1 55 | #elif defined(__linux__) 56 | # define PLATFORM_LINUX 1 57 | #endif 58 | 59 | #if defined(_AMD64_) || defined(__LP64__) || defined(_M_ARM64) 60 | # define PLATFORM_ARCH_64 1 61 | #else 62 | # define PLATFORM_ARCH_32 1 63 | #endif 64 | 65 | #define PLATFORM_CONFIGURED 1 66 | #endif 67 | 68 | #if PLATFORM_WIN 69 | # ifdef _WCHAR_T_DEFINED 70 | typedef wchar_t char_t; 71 | # else 72 | typedef unsigned short char_t; 73 | # endif 74 | #else 75 | typedef char char_t; 76 | #endif 77 | 78 | #if PLATFORM_WIN 79 | # define CSH_EXPORT_API __declspec(dllexport) 80 | # define CSH_CALLTYPE __stdcall 81 | # define CSH_STR_(s1) L ## s1 82 | # define CSH_STR(s) CSH_STR_(s) 83 | #else 84 | # define CSH_EXPORT_API __attribute__((visibility("default"))) 85 | # define CSH_CALLTYPE __stdcall 86 | # define CSH_STR(s) s 87 | #endif 88 | 89 | #define CSH_BEGIN_C extern "C" { 90 | #define CSH_END_C } 91 | #define CSH_EXTERN_C extern "C" 92 | 93 | #define CSH_TOSTRING2(s) #s 94 | #define CSH_TOSTRING(s) CSH_TOSTRING2(s) 95 | 96 | #endif //CSHARPIFY_COMMON_H 97 | -------------------------------------------------------------------------------- /native/include/coreclrhost.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | // 5 | // APIs for hosting CoreCLR 6 | // 7 | 8 | #ifndef __CORECLR_HOST_H__ 9 | #define __CORECLR_HOST_H__ 10 | 11 | #include "common.h" 12 | 13 | #if defined(_WIN32) && defined(_M_IX86) 14 | #define CORECLR_CALLING_CONVENTION __stdcall 15 | #else 16 | #define CORECLR_CALLING_CONVENTION 17 | #endif 18 | 19 | #include 20 | 21 | // For each hosting API, we define a function prototype and a function pointer 22 | // The prototype is useful for implicit linking against the dynamic coreclr 23 | // library and the pointer for explicit dynamic loading (dlopen, LoadLibrary) 24 | #define CORECLR_HOSTING_API(function, ...) \ 25 | extern "C" int CORECLR_CALLING_CONVENTION function(__VA_ARGS__); \ 26 | typedef int (CORECLR_CALLING_CONVENTION *function##_ptr)(__VA_ARGS__) 27 | 28 | // 29 | // Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain 30 | // 31 | // Parameters: 32 | // exePath - Absolute path of the executable that invoked the ExecuteAssembly (the native host application) 33 | // appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly 34 | // propertyCount - Number of properties (elements of the following two arguments) 35 | // propertyKeys - Keys of properties of the app domain 36 | // propertyValues - Values of properties of the app domain 37 | // hostHandle - Output parameter, handle of the created host 38 | // domainId - Output parameter, id of the created app domain 39 | // 40 | // Returns: 41 | // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed 42 | // 43 | CORECLR_HOSTING_API(coreclr_initialize, 44 | const char *exePath, 45 | const char *appDomainFriendlyName, 46 | int propertyCount, 47 | const char **propertyKeys, 48 | const char **propertyValues, 49 | void **hostHandle, 50 | unsigned int *domainId); 51 | 52 | // 53 | // Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host. 54 | // 55 | // Parameters: 56 | // hostHandle - Handle of the host 57 | // domainId - Id of the domain 58 | // 59 | // Returns: 60 | // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed 61 | // 62 | CORECLR_HOSTING_API(coreclr_shutdown, 63 | void *hostHandle, 64 | unsigned int domainId); 65 | 66 | // 67 | // Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host. 68 | // 69 | // Parameters: 70 | // hostHandle - Handle of the host 71 | // domainId - Id of the domain 72 | // latchedExitCode - Latched exit code after domain unloaded 73 | // 74 | // Returns: 75 | // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed 76 | // 77 | CORECLR_HOSTING_API(coreclr_shutdown_2, 78 | void *hostHandle, 79 | unsigned int domainId, 80 | int *latchedExitCode); 81 | 82 | // 83 | // Create a native callable function pointer for a managed method. 84 | // 85 | // Parameters: 86 | // hostHandle - Handle of the host 87 | // domainId - Id of the domain 88 | // entryPointAssemblyName - Name of the assembly which holds the custom entry point 89 | // entryPointTypeName - Name of the type which holds the custom entry point 90 | // entryPointMethodName - Name of the method which is the custom entry point 91 | // delegate - Output parameter, the function stores a native callable function pointer to the delegate at the specified address 92 | // 93 | // Returns: 94 | // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed 95 | // 96 | CORECLR_HOSTING_API(coreclr_create_delegate, 97 | void *hostHandle, 98 | unsigned int domainId, 99 | const char *entryPointAssemblyName, 100 | const char *entryPointTypeName, 101 | const char *entryPointMethodName, 102 | void **delegate); 103 | 104 | // 105 | // Execute a managed assembly with given arguments 106 | // 107 | // Parameters: 108 | // hostHandle - Handle of the host 109 | // domainId - Id of the domain 110 | // argc - Number of arguments passed to the executed assembly 111 | // argv - Array of arguments passed to the executed assembly 112 | // managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint). 113 | // exitCode - Exit code returned by the executed assembly 114 | // 115 | // Returns: 116 | // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed 117 | // 118 | CORECLR_HOSTING_API(coreclr_execute_assembly, 119 | void *hostHandle, 120 | unsigned int domainId, 121 | int argc, 122 | const char **argv, 123 | const char *managedAssemblyPath, 124 | unsigned int *exitCode); 125 | 126 | 127 | // Load an assembly and get a function pointer to a method in it. 128 | CORECLR_HOSTING_API(load_assembly_and_get_function_pointer, 129 | const char_t *assembly_path /* Fully qualified path to assembly */, 130 | const char_t *type_name /* Assembly qualified type name */, 131 | const char_t *method_name /* Public static method name compatible with delegateType */, 132 | const char_t *delegate_type_name /* Assembly qualified delegate type name or null 133 | or UNMANAGEDCALLERSONLY_METHOD if the method is marked with 134 | the UnmanagedCallersOnlyAttribute. */, 135 | void *reserved /* Extensibility parameter (currently unused and must be 0) */, 136 | /*out*/ void **delegate /* Pointer where to store the function pointer result */ 137 | ); 138 | 139 | #undef CORECLR_HOSTING_API 140 | 141 | // 142 | // Callback types used by the hosts 143 | // 144 | typedef bool(CORECLR_CALLING_CONVENTION BundleProbeFn)(const char *path, int64_t *offset, int64_t *size); 145 | 146 | #if !RUNTIME_MONO 147 | typedef const void* (CORECLR_CALLING_CONVENTION PInvokeOverrideFn)(const char* libraryName, const char* entrypointName); 148 | #endif 149 | 150 | #define HOST_PROPERTY_RUNTIME_CONTRACT CSH_STR("HOST_RUNTIME_CONTRACT") 151 | #define HOST_PROPERTY_APP_PATHS CSH_STR("APP_PATHS") 152 | #define HOST_PROPERTY_BUNDLE_PROBE CSH_STR("BUNDLE_PROBE") 153 | #define HOST_PROPERTY_ENTRY_ASSEMBLY_NAME CSH_STR("ENTRY_ASSEMBLY_NAME") 154 | #define HOST_PROPERTY_HOSTPOLICY_EMBEDDED CSH_STR("HOSTPOLICY_EMBEDDED") 155 | #define HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES CSH_STR("NATIVE_DLL_SEARCH_DIRECTORIES") 156 | #define HOST_PROPERTY_PINVOKE_OVERRIDE CSH_STR("PINVOKE_OVERRIDE") 157 | #define HOST_PROPERTY_PLATFORM_RESOURCE_ROOTS CSH_STR"PLATFORM_RESOURCE_ROOTS") 158 | #define HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES CSH_STR("TRUSTED_PLATFORM_ASSEMBLIES") 159 | #define HOST_PROPERTY_RUNTIME_IDENTIFIER CSH_STR("RUNTIME_IDENTIFIER") 160 | #define HOST_PROPERTY_APP_CONTEXT_BASE_DIRECTORY CSH_STR("APP_CONTEXT_BASE_DIRECTORY") // path to where the managed assemblies are (usually at least - RID-specific assemblies will be in subfolders) 161 | 162 | #endif // __CORECLR_HOST_H__ 163 | -------------------------------------------------------------------------------- /native/include/imgui_bridge.h: -------------------------------------------------------------------------------- 1 | #ifndef CSHARPIFY_IMGUI_BRIDGE_H_ 2 | #define CSHARPIFY_IMGUI_BRIDGE_H_ 3 | 4 | void MainLoop(); 5 | 6 | #endif // CSHARPIFY_IMGUI_BRIDGE_H_ -------------------------------------------------------------------------------- /native/include/main.h: -------------------------------------------------------------------------------- 1 | #ifndef CSHARPIFY_MAIN_H_ 2 | #define CSHARPIFY_MAIN_H_ 3 | 4 | int imgui_main(int, char**); 5 | 6 | DNNE_EXTERN_C DNNE_API bool DNNE_CALLTYPE ReturningBool(); 7 | 8 | #endif // CSHARPIFY_MAIN_H_ -------------------------------------------------------------------------------- /native/include/managed_bridge.h: -------------------------------------------------------------------------------- 1 | #ifndef CSHARPIFY_MANAGED_BRIDGE_H_ 2 | #define CSHARPIFY_MANAGED_BRIDGE_H_ 3 | 4 | #include "common.h" 5 | 6 | int load_managed_runtime(); 7 | 8 | int register_icall(const char* name, const void* fnptr); 9 | 10 | #endif // CSHARPIFY_MANAGED_BRIDGE_H_ -------------------------------------------------------------------------------- /native/include/managed_exports.h: -------------------------------------------------------------------------------- 1 | #ifndef CSHARPIFY_MANAGED_EXPORTS_H_ 2 | #define CSHARPIFY_MANAGED_EXPORTS_H_ 3 | 4 | #undef DNNE_COMPILE_AS_SOURCE 5 | #include "exports.h" 6 | 7 | #endif // CSHARPIFY_MANAGED_EXPORTS_H_ -------------------------------------------------------------------------------- /native/include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef CSHARPIFY_UTILS_H_ 2 | #define CSHARPIFY_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | #define RETURN_FAIL_IF_FALSE(exp, msg) { if (!(exp)) { printf(msg); return EXIT_FAILURE; } } 8 | 9 | inline std::string normalizePath(const std::string &messyPath) 10 | { 11 | std::filesystem::path canonicalPath = std::filesystem::absolute( 12 | std::filesystem::weakly_canonical(std::filesystem::path(messyPath))); 13 | return canonicalPath.make_preferred().string(); 14 | } 15 | 16 | inline std::wstring normalizePathW(const std::string &messyPath) 17 | { 18 | std::filesystem::path canonicalPath = std::filesystem::absolute( 19 | std::filesystem::weakly_canonical(std::filesystem::path(messyPath))); 20 | return canonicalPath.make_preferred().wstring(); 21 | } 22 | 23 | inline std::wstring normalizePathW(std::filesystem::path &messyPath) 24 | { 25 | std::filesystem::path canonicalPath = std::filesystem::absolute( 26 | std::filesystem::weakly_canonical(messyPath)); 27 | return canonicalPath.make_preferred().wstring(); 28 | } 29 | 30 | inline int parseManagedSignature(const std::string &full_type, std::string &assembly, std::string &typeAndNamespace, 31 | std::string &nmspace, std::string &type) 32 | { 33 | size_t pos = full_type.find(", "); 34 | typeAndNamespace = full_type.substr(0, pos); 35 | assembly = full_type.substr(pos + 2); 36 | nmspace = {}; 37 | 38 | pos = typeAndNamespace.find('+'); 39 | 40 | if (pos != std::string::npos) { 41 | nmspace = typeAndNamespace.substr(0, pos); 42 | } 43 | 44 | if (!nmspace.empty()) { 45 | const std::filesystem::path typeAsPath(nmspace); 46 | if (typeAsPath.has_extension()) { 47 | auto str = typeAsPath.string(); 48 | auto ext = typeAsPath.extension().string(); 49 | nmspace = str.substr(0, str.length() - ext.length()); 50 | type = ext.substr(1); 51 | type += "/"; 52 | } 53 | } 54 | type += typeAndNamespace.substr(pos + 1); 55 | 56 | return 0; 57 | } 58 | 59 | #if PLATFORM_WIN 60 | #define WIN32_LEAN_AND_MEAN 61 | #define NOMINMAX 62 | #include 63 | 64 | inline std::string UnicodeToString(const std::wstring& wstr) 65 | { 66 | if (wstr.empty()) return {}; 67 | const int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), nullptr, 0, nullptr, nullptr); 68 | std::string strTo(size_needed, 0); 69 | WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), strTo.data(), size_needed, nullptr, nullptr); 70 | return strTo; 71 | } 72 | 73 | inline wchar_t* StringToUnicode(const char* str, int len) 74 | { 75 | const int size_needed = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0); 76 | wchar_t* ret = (wchar_t*)malloc(sizeof(wchar_t*) * size_needed); 77 | MultiByteToWideChar(CP_UTF8, 0, str, len, ret, size_needed); 78 | return ret; 79 | } 80 | 81 | inline std::wstring StringToUnicode(const std::string& str) 82 | { 83 | if (str.empty()) return {}; 84 | const int size_needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0); 85 | std::wstring strTo(size_needed, 0); 86 | MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), strTo.data(), size_needed); 87 | return strTo; 88 | } 89 | 90 | #endif // PLATFORM_WIN 91 | 92 | #endif// CSHARPIFY_UTILS_H_ -------------------------------------------------------------------------------- /native/main.cpp: -------------------------------------------------------------------------------- 1 | #include "managed_exports.h" 2 | #include "main.h" 3 | 4 | #include 5 | 6 | void Example1() 7 | { 8 | struct MyData d; 9 | d.field1 = 2; 10 | d.field2 = 8; 11 | printf("Before: %d", d.field1); 12 | UpdateStructField(&d); 13 | printf("After: %d", d.field1); 14 | } 15 | 16 | 17 | // Called from imgui.gen.cpp on every frame. 18 | void MainLoop() { 19 | // Call the C# method 20 | OnUpdate(); 21 | } 22 | 23 | // This is called from C# 24 | DNNE_EXTERN_C 25 | bool ReturningBool() { 26 | return false; 27 | } 28 | 29 | 30 | // We start here 31 | int main(int argc, char** argv) { 32 | // the first call to a managed function will initialize the runtime, but it can also be initialized 33 | // ahead of time with this call. 34 | // load_managed_runtime(); 35 | 36 | // This is a C# method. 37 | OnStart(); 38 | 39 | // Start up the imgui loop in imgui.gen.cpp 40 | return imgui_main(argc, argv); 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /native/mono/bridge.h: -------------------------------------------------------------------------------- 1 | #ifndef __CSHARPIFY_MONO_BRIDGE_H__ 2 | #define __CSHARPIFY_MONO_BRIDGE_H__ 3 | 4 | #include "config.h" 5 | 6 | #if RUNTIME_MONO 7 | 8 | #include "coreclr_delegates.h" 9 | #include "coreclrhost.h" 10 | #include "runtime.h" 11 | 12 | static MonoCoreRuntimeProperties monovm_core_properties = { 13 | nullptr, 14 | nullptr, 15 | nullptr, 16 | nullptr 17 | }; 18 | 19 | #endif 20 | 21 | #endif -------------------------------------------------------------------------------- /native/mono/mono.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "common.h" 3 | 4 | #if RUNTIME_MONO 5 | 6 | #include "managed_exports.h" 7 | #include "bridge.h" 8 | #include "utils.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | namespace fs = std::filesystem; 20 | 21 | static bool initialized; 22 | 23 | static MonoAssembly* entry_assembly = nullptr; 24 | 25 | MonoAssembly* 26 | assembly_preload_hook(MonoAssemblyName* aname, char** assemblies_path, void* user_data) { 27 | char filename[1024]; 28 | char path[1024]; 29 | 30 | fs::path name(mono_assembly_name_get_name(aname)); 31 | if (!name.has_extension() || name.extension() != "dll") { 32 | name.replace_filename(name.string().append(".dll")); 33 | } 34 | 35 | auto basePath = normalizePath("."); 36 | auto runtimePath = fs::path{normalizePath("sdk")}; 37 | 38 | fs::path possible = fs::path{runtimePath / name}; 39 | if (exists(possible)) { 40 | return mono_assembly_open(possible.c_str(), nullptr); 41 | } 42 | 43 | possible = fs::path(basePath / name); 44 | if (exists(possible)) { 45 | return mono_assembly_open(possible.c_str(), nullptr); 46 | } 47 | 48 | return nullptr; 49 | } 50 | 51 | static void* load_symbol(void* handle, const std::string &name) { 52 | assert(!name.empty()); 53 | 54 | void* ret; 55 | if (!handle) { 56 | ret = dlsym(RTLD_SELF, name.c_str()); 57 | } else { 58 | ret = dlsym(handle, name.c_str()); 59 | } 60 | assert(ret != nullptr); 61 | return ret; 62 | } 63 | 64 | CSHARPIFY_BEGIN_C 65 | void* pinvoke_override(const char* libraryName, const char* entrypointName) { 66 | void* symbol = nullptr; 67 | if (!strcmp(libraryName, "__Internal") || 68 | !strcmp(libraryName, "cimgui")) { 69 | symbol = load_symbol(nullptr, entrypointName); 70 | } 71 | return symbol; 72 | } 73 | CSHARPIFY_END_C 74 | 75 | 76 | char* strdup_printf(int* len, const char* msg, ...) { 77 | // COOP: no managed memory access: any mode 78 | va_list args; 79 | char* formatted = NULL; 80 | 81 | va_start (args, msg); 82 | *len = vasprintf(&formatted, msg, args); 83 | va_end (args); 84 | 85 | return formatted; 86 | } 87 | 88 | int load_managed_runtime() { 89 | fs::path assemblyPath = "."; 90 | auto assemblyName = ASSEMBLYNAME ".dll"; 91 | fs::path startAssembly = assemblyPath / assemblyName; 92 | 93 | auto basePath = normalizePath("."); 94 | auto runtimePath = fs::path{normalizePath("sdk")}; 95 | 96 | const char* propertyKeys[] = { 97 | HOST_PROPERTY_APP_CONTEXT_BASE_DIRECTORY, // path to where the managed assemblies are (usually at least - RID-specific assemblies will be in subfolders) 98 | HOST_PROPERTY_RUNTIME_IDENTIFIER 99 | }; 100 | 101 | const char* propertyValues[] = { 102 | basePath.c_str(), 103 | runtime_identifier 104 | }; 105 | 106 | monovm_core_properties.pinvoke_override = &pinvoke_override; 107 | 108 | int rv = monovm_initialize_preparsed( 109 | &monovm_core_properties, 110 | sizeof(propertyKeys) / sizeof(char*), 111 | propertyKeys, 112 | propertyValues 113 | ); 114 | 115 | MonovmRuntimeConfigArguments runtime_config_args; 116 | 117 | mono_debug_init(MONO_DEBUG_FORMAT_MONO); 118 | mono_install_assembly_preload_hook(assembly_preload_hook, nullptr); 119 | 120 | mono_set_signal_chaining(1); 121 | mono_set_crash_chaining(1); 122 | mono_jit_init(ASSEMBLYNAME); 123 | 124 | // The mono initialization resets the preload hooks, so install it again 125 | mono_install_assembly_preload_hook(assembly_preload_hook, nullptr); 126 | 127 | MonoImageOpenStatus status = MONO_IMAGE_OK; 128 | entry_assembly = mono_assembly_open(assemblyName, &status); 129 | initialized = true; 130 | return rv; 131 | } 132 | 133 | #include 134 | 135 | int register_icall(const char* name, const void* fnptr) { 136 | mono_add_internal_call(name, fnptr); 137 | return 0; 138 | } 139 | 140 | CSHARPIFY_BEGIN_C 141 | 142 | MonoMethod* 143 | mono_marshal_get_managed_wrapper(MonoMethod* method, MonoClass* delegate_klass, MonoGCHandle target_handle, 144 | MonoError* error); 145 | void* 146 | mono_compile_method_checked(MonoMethod* method, MonoError* error); 147 | #define is_ok(error) ((error).error_code == MONO_ERROR_NONE) 148 | void* 149 | ves_icall_RuntimeMethodHandle_GetFunctionPointer_raw(MonoMethod* method, MonoError* error); 150 | 151 | void* get_fast_callable_managed_function( 152 | const char_t* dotnet_type, 153 | const char_t* dotnet_type_method) { 154 | 155 | if (!initialized) { 156 | load_managed_runtime(); 157 | } 158 | 159 | std::string nmspace; 160 | std::string type; 161 | std::string typeAndNamespace; 162 | std::string assembly; 163 | parseManagedSignature(dotnet_type, assembly, typeAndNamespace, nmspace, type); 164 | 165 | void* ptr = nullptr; 166 | 167 | /* 168 | * A pure (naive, no cache, etc) mono implementation would do this. 169 | * mono_marshal_get_managed_wrapper is not exposed in the microsoft.netcore.app.runtime.mono.[rid] package library, 170 | * but ves_icall_RuntimeMethodHandle_GetFunctionPointer directly calls it for methods marked with 171 | * UnmanagedCallersOnly, so it does what we need it to do. 172 | 173 | MonoImage *image = mono_assembly_get_image (entry_assembly); 174 | MonoClass *klass = mono_class_from_name(image, nmspace.c_str(), type.c_str()); 175 | MonoMethod *method = mono_class_get_method_from_name(klass, dotnet_type_method, -1); 176 | 177 | MonoError error; 178 | MonoClass *delegate_klass = nullptr; 179 | MonoGCHandle target_handle = nullptr; 180 | ptr = ves_icall_RuntimeMethodHandle_GetFunctionPointer_raw(method, &error); 181 | */ 182 | 183 | /* 184 | * But coreclr_create_delegate was implemented in the Mono VM in .net 7 185 | * https://github.com/lambdageek/runtime/commit/5c30a82505071936507669f8b6f490b98c1bfb41 186 | * So we can use the same call on both coreclr and mono. 187 | * No domain handle or id is needed, Mono doesn't use it 188 | */ 189 | 190 | int rv = coreclr_create_delegate(nullptr, 0, assembly.c_str(), typeAndNamespace.c_str(), dotnet_type_method, &ptr); 191 | return ptr; 192 | } 193 | 194 | CSHARPIFY_END_C 195 | 196 | #endif 197 | -------------------------------------------------------------------------------- /native/mono/runtime.h: -------------------------------------------------------------------------------- 1 | #ifndef CSHARPIFY_MONO_RUNTIME_H_ 2 | #define CSHARPIFY_MONO_RUNTIME_H_ 3 | 4 | #include "mono/jit/mono-private-unstable.h" 5 | 6 | #endif -------------------------------------------------------------------------------- /native/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 8 | #include 9 | 10 | std::string normalizePath(const std::string &messyPath) 11 | 12 | int parseManagedSignature(const std::string &full_type, std::string &assembly, std::string &typeAndNamespace, 13 | std::string &nmspace, std::string &type) { 14 | size_t pos = full_type.find(", "); 15 | typeAndNamespace = full_type.substr(0, pos); 16 | assembly = full_type.substr(pos + 2); 17 | nmspace = {}; 18 | 19 | pos = typeAndNamespace.find('+'); 20 | 21 | if (pos != std::string::npos) { 22 | nmspace = typeAndNamespace.substr(0, pos); 23 | } 24 | 25 | if (!nmspace.empty()) { 26 | const std::filesystem::path typeAsPath(nmspace); 27 | if (typeAsPath.has_extension()) { 28 | auto str = typeAsPath.string(); 29 | auto ext = typeAsPath.extension().string(); 30 | nmspace = str.substr(0, str.length() - ext.length()); 31 | type = ext.substr(1); 32 | type += "/"; 33 | } 34 | } 35 | type += typeAndNamespace.substr(pos + 1); 36 | 37 | return 0; 38 | } 39 | 40 | 41 | #if PLATFORM_WIN 42 | #define WIN32_LEAN_AND_MEAN 43 | #define NOMINMAX 44 | #include 45 | 46 | std::string UnicodeToString(const std::wstring& wstr) 47 | { 48 | if (wstr.empty()) return {}; 49 | const int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), nullptr, 0, nullptr, nullptr); 50 | std::string strTo(size_needed, 0); 51 | WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), strTo.data(), size_needed, nullptr, nullptr); 52 | return strTo; 53 | } 54 | 55 | std::wstring StringToUnicode(const std::string& str) 56 | { 57 | if (str.empty()) return {}; 58 | const int size_needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0); 59 | std::wstring strTo(size_needed, 0); 60 | MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), strTo.data(), size_needed); 61 | return strTo; 62 | } 63 | 64 | char_t* StringToUnicode(const char* str, int len) 65 | { 66 | const int size_needed = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0); 67 | char_t* ret = (char_t*)malloc(sizeof(char_t*) * size_needed); 68 | MultiByteToWideChar(CP_UTF8, 0, str, len, ret, size_needed); 69 | return ret; 70 | } 71 | 72 | wchar_t* StringToUnicode(const char* str, int len) 73 | { 74 | const int size_needed = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0); 75 | wchar_t* ret = (wchar_t*)malloc(sizeof(wchar_t*) * size_needed); 76 | MultiByteToWideChar(CP_UTF8, 0, str, len, ret, size_needed); 77 | return ret; 78 | } 79 | #else 80 | std::string UnicodeToString(const std::wstring& wstr) 81 | { 82 | if (wstr.empty()) return {}; 83 | const int size_needed = wcstombs(nullptr, wstr.data(), wstr.size()); 84 | std::string strTo(size_needed, 0); 85 | wcstombs(strTo.data(), wstr.data(), size_needed); 86 | return strTo; 87 | } 88 | 89 | std::string UnicodeToString(const std::u16string& wstr) 90 | { 91 | if (wstr.empty()) return {}; 92 | std::wstring_convert, char16_t> conversion; 93 | return (conversion.to_bytes(wstr.data())); 94 | } 95 | 96 | std::wstring StringToUnicode(const std::string& str) 97 | { 98 | if (str.empty()) return {}; 99 | const int size_needed = mbstowcs(nullptr, str.data(), str.size()); 100 | std::wstring strTo(size_needed, 0); 101 | mbstowcs(strTo.data(), str.data(), size_needed); 102 | return strTo; 103 | } 104 | 105 | wchar_t* StringToUnicode(const char* str, int len) 106 | { 107 | const int size_needed = mbstowcs(nullptr, str, len); 108 | wchar_t* ret = (wchar_t*)malloc(sizeof(wchar_t*) * size_needed); 109 | mbstowcs(ret, str, size_needed); 110 | return ret; 111 | } 112 | #endif -------------------------------------------------------------------------------- /pack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | { set +x; } 2>/dev/null 4 | SOURCE=$0 5 | DIR="$( pwd )" 6 | 7 | CONFIGURATION=Debug 8 | PRESET= 9 | ARGSONLY=0 10 | ARGS= 11 | 12 | while (( "$#" )); do 13 | if [[ x"$ARGSONLY" == x"1" ]]; then 14 | ARGS="${ARGS} $1" 15 | shift 16 | continue 17 | fi 18 | 19 | case "$1" in 20 | -d|--debug) 21 | CONFIGURATION="Debug" 22 | ;; 23 | -r|--release) 24 | CONFIGURATION="Release" 25 | ;; 26 | -c|--configuration) 27 | shift 28 | CONFIGURATION=$1 29 | ;; 30 | pc|--coreclr) 31 | PRESET=coreclr 32 | ;; 33 | pm|--mono) 34 | PRESET=mono 35 | ;; 36 | pn|--nativeaot) 37 | PRESET=nativeaot 38 | ;; 39 | -v|--verbose) 40 | ARGS="${ARGS} --verbose" 41 | ;; 42 | --args) 43 | ARGSONLY=1 44 | ;; 45 | --trace) 46 | { set -x; } 2>/dev/null 47 | ;; 48 | *) 49 | ARGS="${ARGS} $1" 50 | ;; 51 | esac 52 | shift 53 | done 54 | 55 | cmake --preset $PRESET 56 | cpack --preset $PRESET 57 | cp build/$PRESET/csharpify-*-all.zip . -------------------------------------------------------------------------------- /packages/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spoiledcat/csharpify/bb793eb9cfde0587ef1be39c8cd32a2e628fd450/packages/.gitignore -------------------------------------------------------------------------------- /packages/DNNE.2.0.6.2.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spoiledcat/csharpify/bb793eb9cfde0587ef1be39c8cd32a2e628fd450/packages/DNNE.2.0.6.2.nupkg -------------------------------------------------------------------------------- /packages/ImGui.NET.1.90.1.1.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spoiledcat/csharpify/bb793eb9cfde0587ef1be39c8cd32a2e628fd450/packages/ImGui.NET.1.90.1.1.nupkg -------------------------------------------------------------------------------- /packages/SDL2-CS.2.0.30.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spoiledcat/csharpify/bb793eb9cfde0587ef1be39c8cd32a2e628fd450/packages/SDL2-CS.2.0.30.nupkg --------------------------------------------------------------------------------