jacksondunstan / UnityNativeScripting

Unity Scripting in C++
https://jacksondunstan.com/articles/3938
MIT License
1.33k stars 135 forks source link

Couldn't open Native Library #55

Closed SeleDreams closed 4 years ago

SeleDreams commented 4 years ago

Hi, I'm posting this issue because I don't know why, Unity refuses to load the Native Library, is it because the architecture is x86 ? I did set the project to x86 though so I don't think this is the reason.

image

SeleDreams commented 4 years ago

I found the issue using GetLastError, and it makes me think some things could be changed.

Basically, because the C++ is being used in the editor, as the editor is 64 bits only, it cannot run Win32 libraries, and that is a problem in the case we want to make a 32 bits game, it makes the process more tedious as we have to make a separate build for the editor and the game

jacksondunstan commented 4 years ago

@SeleDreams I'm glad you found the issue. Do you have a suggestion for how the project could be improved to be less "tedious?"

SeleDreams commented 4 years ago

@SeleDreams I'm glad you found the issue. Do you have a suggestion for how the project could be improved to be less "tedious?"

The cmake system could be made to have both an x64 and an x86 version of the dll that are present with their arch appended to their name and the script loading the dll would load the right one based on the architecture, it would make things a lot easier (it should also display the error code too to allow people to know the reason if there is an issue)

Also, it would be nice if more of the Unity API was pre-applied to the json, as I have to manually add a lot of things like AddComponent, UnityEngine.UI.Text,new GameObject(string) etc etc that usually seem like "obvious stuff", it makes the experience a lot less pleasant since more time is spent recreating the Unity API than making stuff

technically, I kind of wonder if it couldn't be done automatically through reflection, a script iterating through absolutely all the scripts from an assembly and generating a json with all the publicly accessible properties and methods

while adding some types by the way, I have noticed two bugs, one where it was impossible to put a class name without namespace (so types from the global namespace) and one that was appending system if a type was in the global namespace

I fixed them both, I will post a pull request in order to merge these fixes

jacksondunstan commented 4 years ago

@SeleDreams I'd recommend running the CMake generator twice: once for the editor and once for the standalone build in different directories. You might want to run it even more times if you need additional standalone builds, such as a 32-bit version. Then you can write a tiny batch file that builds them all at once or you can build them individually for faster builds. I'd really prefer not to make this the default as fast compile times is one of the goals of the project.

Displaying the error code when loading the DLL fails is a good idea. I'd happily accept a PR with this change.

As for needing to build up the JSON file to get access to parts of the Unity API, I understand the frustration here. The goal was to minimize the amount of bloat introduced into a project, so the design is an "opt-in" approach. An "out-out" approach can be even harder to use as it often entails untangling a bunch of interfaces and dependencies. I agree that this is an area that could do with some usability improvement, especially for projects that don't care about the bloat. A reflection-based script to generate the JSON is definitely one way to rather easily add the whole Unity API. Adding just a subset is a lot trickier though. I'm open to ideas and PRs here as well.

Looking forward to seeing those bug fixes. Thanks so much!

SeleDreams commented 4 years ago

@SeleDreams I'd recommend running the CMake generator twice: once for the editor and once for the standalone build in different directories. You might want to run it even more times if you need additional standalone builds, such as a 32-bit version. Then you can write a tiny batch file that builds them all at once or you can build them individually for faster builds. I'd really prefer not to make this the default as fast compile times is one of the goals of the project.

Displaying the error code when loading the DLL fails is a good idea. I'd happily accept a PR with this change.

As for needing to build up the JSON file to get access to parts of the Unity API, I understand the frustration here. The goal was to minimize the amount of bloat introduced into a project, so the design is an "opt-in" approach. An "out-out" approach can be even harder to use as it often entails untangling a bunch of interfaces and dependencies. I agree that this is an area that could do with some usability improvement, especially for projects that don't care about the bloat. A reflection-based script to generate the JSON is definitely one way to rather easily add the whole Unity API. Adding just a subset is a lot trickier though. I'm open to ideas and PRs here as well.

Looking forward to seeing those bug fixes. Thanks so much!

Well, since the unity api is now split into multiple dll files, I feel like there could be one json per dll. Like this it would add only what we want to use.

I would by the way have a question, let's say I need from C++ to be able to compare two System::String how would I do that ? I thought the handle would maybe give me a char* but it doesn't seem to be the case I'd basically want to get an LPSTR from a String

jacksondunstan commented 4 years ago

There's no built-in way to copy the characters of a C# System.String into C++ memory, but it should be relatively easy to compare them if you make a helper function like this and expose it in the JSON:

public static bool AreStringsEqual(string a, string b) { return a == b; }
SeleDreams commented 4 years ago

That's what I ended up doing

but since from C# it would be easy for modders to trick the code I made a fake call to this function first that was verifying if two strings that are sure to not be equal return a true result