Refactor generated bindings P/Invoke to support name mangling for symbols
This commit is contained in:
@@ -176,7 +176,6 @@ bool ScriptsBuilder::IsReady()
|
||||
|
||||
void ScriptsBuilder::MarkWorkspaceDirty()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEditor.ScriptsBuilder::Internal_MarkWorkspaceDirty")
|
||||
ScopeLock scopeLock(_locker);
|
||||
_lastSourceCodeEdited = DateTime::Now();
|
||||
_wasProjectStructureChanged = true;
|
||||
@@ -184,7 +183,6 @@ void ScriptsBuilder::MarkWorkspaceDirty()
|
||||
|
||||
void ScriptsBuilder::CheckForCompile()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEditor.ScriptsBuilder::Internal_CheckForCompile")
|
||||
ScopeLock scopeLock(_locker);
|
||||
if (IsSourceDirty())
|
||||
Compile();
|
||||
@@ -207,7 +205,6 @@ void ScriptsBuilderImpl::onScriptsReloadEnd()
|
||||
|
||||
void ScriptsBuilder::Compile()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEditor.ScriptsBuilder::Internal_Compile")
|
||||
ScopeLock scopeLock(_locker);
|
||||
|
||||
// Request compile job
|
||||
|
||||
@@ -260,15 +260,15 @@ namespace FlaxEngine
|
||||
|
||||
#region Internal Calls
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.AnimationGraph::Internal_HasConnection")]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "AnimGraphInternal_HasConnection")]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
internal static partial bool Internal_HasConnection(ref AnimationGraph.CustomNode.Context context, int boxId);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.AnimationGraph::Internal_GetInputValue")]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "AnimGraphInternal_GetInputValue")]
|
||||
[return: MarshalUsing(typeof(FlaxEngine.ManagedHandleMarshaller))]
|
||||
internal static partial object Internal_GetInputValue(ref AnimationGraph.CustomNode.Context context, int boxId);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.AnimationGraph::Internal_GetOutputImpulseData")]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "AnimGraphInternal_GetOutputImpulseData")]
|
||||
internal static partial IntPtr Internal_GetOutputImpulseData(ref AnimationGraph.CustomNode.Context context);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
#pragma clang diagnostic ignored "-Wnull-dereference"
|
||||
#pragma clang diagnostic ignored "-Winvalid-noreturn"
|
||||
|
||||
#define SCRIPTING_EXPORT(name)
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
#define DLLEXPORT __attribute__ ((__visibility__ ("default")))
|
||||
@@ -88,8 +86,6 @@
|
||||
|
||||
#pragma warning(disable: 4251)
|
||||
|
||||
#define SCRIPTING_EXPORT(name) __pragma(comment(linker, "/EXPORT:" #name "=" __FUNCDNAME__))
|
||||
|
||||
#else
|
||||
|
||||
#pragma error "Unknown compiler."
|
||||
|
||||
@@ -1323,7 +1323,6 @@ bool Level::SaveAllScenes()
|
||||
|
||||
void Level::SaveAllScenesAsync()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Level::Internal_SaveAllScenesAsync")
|
||||
ScopeLock lock(_sceneActionsLocker);
|
||||
for (int32 i = 0; i < Scenes.Count(); i++)
|
||||
_sceneActions.Enqueue(New<SaveSceneAction>(Scenes[i]));
|
||||
@@ -1428,7 +1427,6 @@ bool Level::UnloadAllScenes()
|
||||
|
||||
void Level::UnloadAllScenesAsync()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Level::Internal_UnloadAllScenesAsync")
|
||||
ScopeLock lock(_sceneActionsLocker);
|
||||
_sceneActions.Enqueue(New<UnloadScenesAction>());
|
||||
}
|
||||
|
||||
@@ -304,7 +304,6 @@ bool NetworkManager::StartHost()
|
||||
|
||||
void NetworkManager::Stop()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Networking.NetworkManager::Internal_Stop");
|
||||
if (Mode == NetworkManagerMode::Offline && State == NetworkConnectionState::Offline)
|
||||
return;
|
||||
PROFILE_CPU();
|
||||
|
||||
@@ -16,7 +16,6 @@ typedef struct _DROPFILES
|
||||
|
||||
void WindowsClipboard::Clear()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Clipboard::Internal_Clear");
|
||||
OpenClipboard(nullptr);
|
||||
EmptyClipboard();
|
||||
CloseClipboard();
|
||||
|
||||
@@ -700,7 +700,6 @@ void Render2D::Begin(GPUContext* context, GPUTextureView* output, GPUTextureView
|
||||
|
||||
void Render2D::End()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Render2D::Internal_End")
|
||||
RENDER2D_CHECK_RENDERING_STATE;
|
||||
ASSERT(Context != nullptr && Output != nullptr);
|
||||
ASSERT(GUIShader != nullptr);
|
||||
@@ -816,7 +815,6 @@ void Render2D::PeekTransform(Matrix3x3& transform)
|
||||
|
||||
void Render2D::PopTransform()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Render2D::Internal_PopTransform")
|
||||
RENDER2D_CHECK_RENDERING_STATE;
|
||||
|
||||
ASSERT(TransformLayersStack.HasItems());
|
||||
@@ -858,7 +856,6 @@ void Render2D::PeekClip(Rectangle& clipRect)
|
||||
|
||||
void Render2D::PopClip()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Render2D::Internal_PopClip")
|
||||
RENDER2D_CHECK_RENDERING_STATE;
|
||||
|
||||
ClipLayersStack.Pop();
|
||||
@@ -880,7 +877,6 @@ void Render2D::PeekTint(Color& tint)
|
||||
|
||||
void Render2D::PopTint()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Render2D::Internal_PopTint")
|
||||
RENDER2D_CHECK_RENDERING_STATE;
|
||||
|
||||
TintLayersStack.Pop();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "Engine/Platform/FileSystem.h"
|
||||
#include "Engine/Animations/Graph/AnimGraph.h"
|
||||
#include "Engine/Scripting/InternalCalls.h"
|
||||
#include "Engine/Scripting/MException.h"
|
||||
@@ -8,82 +7,69 @@
|
||||
|
||||
#if !COMPILE_WITHOUT_CSHARP
|
||||
|
||||
namespace UtilsInternal
|
||||
#if USE_MONO && !USE_NETCORE
|
||||
DEFINE_INTERNAL_CALL(MonoObject*) UtilsInternal_ExtractArrayFromList(MonoObject* obj)
|
||||
{
|
||||
MonoObject* ExtractArrayFromList(MonoObject* obj)
|
||||
{
|
||||
#if USE_MONO
|
||||
auto klass = mono_object_get_class(obj);
|
||||
auto field = mono_class_get_field_from_name(klass, "_items");
|
||||
MonoObject* o;
|
||||
mono_field_get_value(obj, field, &o);
|
||||
return o;
|
||||
#else
|
||||
SCRIPTING_EXPORT("FlaxEngine.Utils::Internal_ExtractArrayFromList")
|
||||
return nullptr;
|
||||
auto klass = mono_object_get_class(obj);
|
||||
auto field = mono_class_get_field_from_name(klass, "_items");
|
||||
MonoObject* o;
|
||||
mono_field_get_value(obj, field, &o);
|
||||
return o;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) PlatformInternal_MemoryCopy(void* dst, const void* src, uint64 size)
|
||||
{
|
||||
Platform::MemoryCopy(dst, src, size);
|
||||
}
|
||||
|
||||
namespace DebugLogHandlerInternal
|
||||
DEFINE_INTERNAL_CALL(void) PlatformInternal_MemoryClear(void* dst, uint64 size)
|
||||
{
|
||||
void LogWrite(LogType level, MonoString* msgObj)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.DebugLogHandler::Internal_LogWrite")
|
||||
StringView msg;
|
||||
MUtils::ToString(msgObj, msg);
|
||||
Log::Logger::Write(level, msg);
|
||||
}
|
||||
|
||||
void Log(LogType level, MonoString* msgObj, ScriptingObject* obj, MonoString* stackTrace)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.DebugLogHandler::Internal_Log")
|
||||
|
||||
if (msgObj == nullptr)
|
||||
return;
|
||||
|
||||
// Get info
|
||||
StringView msg;
|
||||
MUtils::ToString(msgObj, msg);
|
||||
//const String objName = obj ? obj->ToString() : String::Empty;
|
||||
|
||||
// Send event
|
||||
// TODO: maybe option for build to threat warnings and errors as fatal errors?
|
||||
//const String logMessage = String::Format(TEXT("Debug:{1} {2}"), objName, *msg);
|
||||
Log::Logger::Write(level, msg);
|
||||
}
|
||||
|
||||
|
||||
void LogException(MonoException* exception, ScriptingObject* obj)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.DebugLogHandler::Internal_LogException")
|
||||
#if USE_MONO
|
||||
if (exception == nullptr)
|
||||
return;
|
||||
|
||||
// Get info
|
||||
MException ex(exception);
|
||||
const String objName = obj ? obj->ToString() : String::Empty;
|
||||
|
||||
// Print exception including inner exceptions
|
||||
// TODO: maybe option for build to threat warnings and errors as fatal errors?
|
||||
ex.Log(LogType::Warning, objName.GetText());
|
||||
#endif
|
||||
}
|
||||
|
||||
Platform::MemoryClear(dst, size);
|
||||
}
|
||||
|
||||
namespace FlaxLogWriterInternal
|
||||
DEFINE_INTERNAL_CALL(int32) PlatformInternal_MemoryCompare(const void* buf1, const void* buf2, uint64 size)
|
||||
{
|
||||
void WriteStringToLog(MonoString* msgObj)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.FlaxLogWriter::Internal_WriteStringToLog")
|
||||
if (msgObj == nullptr)
|
||||
return;
|
||||
StringView msg;
|
||||
MUtils::ToString(msgObj, msg);
|
||||
LOG_STR(Info, msg);
|
||||
}
|
||||
return Platform::MemoryCompare(buf1, buf2, size);
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) DebugLogHandlerInternal_LogWrite(LogType level, MonoString* msgObj)
|
||||
{
|
||||
StringView msg;
|
||||
MUtils::ToString(msgObj, msg);
|
||||
Log::Logger::Write(level, msg);
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) DebugLogHandlerInternal_Log(LogType level, MonoString* msgObj, ScriptingObject* obj, MonoString* stackTrace)
|
||||
{
|
||||
if (msgObj == nullptr)
|
||||
return;
|
||||
|
||||
// Get info
|
||||
StringView msg;
|
||||
MUtils::ToString(msgObj, msg);
|
||||
//const String objName = obj ? obj->ToString() : String::Empty;
|
||||
|
||||
// Send event
|
||||
// TODO: maybe option for build to threat warnings and errors as fatal errors?
|
||||
//const String logMessage = String::Format(TEXT("Debug:{1} {2}"), objName, *msg);
|
||||
Log::Logger::Write(level, msg);
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) DebugLogHandlerInternal_LogException(MonoException* exception, ScriptingObject* obj)
|
||||
{
|
||||
#if USE_MONO
|
||||
if (exception == nullptr)
|
||||
return;
|
||||
|
||||
// Get info
|
||||
MException ex(exception);
|
||||
const String objName = obj ? obj->ToString() : String::Empty;
|
||||
|
||||
// Print exception including inner exceptions
|
||||
// TODO: maybe option for build to threat warnings and errors as fatal errors?
|
||||
ex.Log(LogType::Warning, objName.GetText());
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -92,13 +78,14 @@ void registerFlaxEngineInternalCalls()
|
||||
{
|
||||
AnimGraphExecutor::initRuntime();
|
||||
#if USE_MONO
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Utils::MemoryCopy", &Platform::MemoryCopy);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Utils::MemoryClear", &Platform::MemoryClear);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Utils::MemoryCompare", &Platform::MemoryCompare);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Utils::MemoryCopy", &PlatformInternal_MemoryCopy);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Utils::MemoryClear", &PlatformInternal_MemoryClear);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Utils::MemoryCompare", &PlatformInternal_MemoryCompare);
|
||||
#if USE_MONO && !USE_NETCORE
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Utils::Internal_ExtractArrayFromList", &UtilsInternal::ExtractArrayFromList);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.DebugLogHandler::Internal_LogWrite", &DebugLogHandlerInternal::LogWrite);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.DebugLogHandler::Internal_Log", &DebugLogHandlerInternal::Log);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.DebugLogHandler::Internal_LogException", &DebugLogHandlerInternal::LogException);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.FlaxLogWriter::Internal_WriteStringToLog", &FlaxLogWriterInternal::WriteStringToLog);
|
||||
#endif
|
||||
ADD_INTERNAL_CALL("FlaxEngine.DebugLogHandler::Internal_LogWrite", &DebugLogHandlerInternal_LogWrite);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.DebugLogHandler::Internal_Log", &DebugLogHandlerInternal_Log);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.DebugLogHandler::Internal_LogException", &DebugLogHandlerInternal_LogException);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ namespace Flax.Build.Bindings
|
||||
private static readonly List<string> CSharpUsedNamespacesSorted = new List<string>();
|
||||
private static readonly List<string> CSharpAdditionalCode = new List<string>();
|
||||
private static readonly Dictionary<string, string> CSharpAdditionalCodeCache = new Dictionary<string, string>();
|
||||
#if USE_NETCORE
|
||||
private static readonly List<FunctionInfo.ParameterInfo> CSharpEventBindParams = new List<FunctionInfo.ParameterInfo>() { new FunctionInfo.ParameterInfo() { Name = "bind", Type = new TypeInfo("bool") } };
|
||||
#endif
|
||||
|
||||
public static event Action<BuildData, ApiTypeInfo, StringBuilder, string> GenerateCSharpTypeInternals;
|
||||
|
||||
@@ -512,7 +515,9 @@ namespace Flax.Build.Bindings
|
||||
contents.AppendLine().Append(indent).Append("[MethodImpl(MethodImplOptions.InternalCall)]");
|
||||
contents.AppendLine().Append(indent).Append("internal static partial ");
|
||||
#else
|
||||
contents.AppendLine().Append(indent).Append($"[LibraryImport(\"{caller.ParentModule.Module.BinaryModuleName}\", EntryPoint = \"{caller.FullNameManaged}::Internal_{functionInfo.UniqueName}\", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]");
|
||||
if (string.IsNullOrEmpty(functionInfo.Glue.LibraryEntryPoint))
|
||||
throw new Exception($"Function {caller.FullNameNative}::{functionInfo.Name} has missing entry point for library import.");
|
||||
contents.AppendLine().Append(indent).Append($"[LibraryImport(\"{caller.ParentModule.Module.BinaryModuleName}\", EntryPoint = \"{functionInfo.Glue.LibraryEntryPoint}\", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]");
|
||||
if (!string.IsNullOrEmpty(returnMarshalType))
|
||||
contents.AppendLine().Append(indent).Append($"[return: {returnMarshalType}]");
|
||||
contents.AppendLine().Append(indent).Append("internal static partial ");
|
||||
@@ -1000,7 +1005,12 @@ namespace Flax.Build.Bindings
|
||||
contents.Append("IntPtr obj, ");
|
||||
contents.Append("bool bind);");
|
||||
#else
|
||||
contents.Append(indent).Append($"[LibraryImport(\"{classInfo.ParentModule.Module.BinaryModuleName}\", EntryPoint = \"{classInfo.FullNameManaged}::Internal_{eventInfo.Name}_Bind\", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]").AppendLine();
|
||||
string libraryEntryPoint;
|
||||
if (buildData.Toolchain.Compiler == TargetCompiler.MSVC)
|
||||
libraryEntryPoint = $"{classInfo.FullNameManaged}::Internal_{eventInfo.Name}_Bind"; // MSVC allows to override exported symbol name
|
||||
else
|
||||
libraryEntryPoint = CppNameMangling.MangleFunctionName(buildData, eventInfo.Name + "_ManagedBind", classInfo.FullNameNativeInternal + "Internal", CSharpEventBindParams);
|
||||
contents.Append(indent).Append($"[LibraryImport(\"{classInfo.ParentModule.Module.BinaryModuleName}\", EntryPoint = \"{libraryEntryPoint}\", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]").AppendLine();
|
||||
contents.Append(indent).Append($"internal static partial void Internal_{eventInfo.Name}_Bind(");
|
||||
if (!eventInfo.IsStatic)
|
||||
contents.Append("IntPtr obj, ");
|
||||
|
||||
@@ -871,7 +871,6 @@ namespace Flax.Build.Bindings
|
||||
return true;
|
||||
if (typeInfo.IsPtr || typeInfo.IsRef || typeInfo.IsArray || typeInfo.IsBitField || (typeInfo.GenericArgs != null && typeInfo.GenericArgs.Count != 0))
|
||||
return false;
|
||||
#if !USE_NETCORE
|
||||
if (CSharpNativeToManagedBasicTypes.ContainsKey(typeInfo.Type) || CSharpNativeToManagedBasicTypes.ContainsValue(typeInfo.Type))
|
||||
return true;
|
||||
var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
|
||||
@@ -880,7 +879,6 @@ namespace Flax.Build.Bindings
|
||||
if (apiType.IsEnum)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -899,8 +897,9 @@ namespace Flax.Build.Bindings
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void GenerateCppWrapperFunction(BuildData buildData, StringBuilder contents, ApiTypeInfo caller, FunctionInfo functionInfo, string callFormat = "{0}({1})")
|
||||
private static void GenerateCppWrapperFunction(BuildData buildData, StringBuilder contents, ApiTypeInfo caller, string callerName, FunctionInfo functionInfo, string callFormat = "{0}({1})")
|
||||
{
|
||||
#if !USE_NETCORE
|
||||
// Optimize static function wrappers that match C# internal call ABI exactly
|
||||
// Use it for Engine-internally only because in games this makes it problematic to use the same function name but with different signature that is not visible to scripting
|
||||
if (CurrentModule.Module is EngineModule && callFormat == "{0}({1})" && GenerateCppWrapperFunctionImplicitBinding(buildData, functionInfo, caller))
|
||||
@@ -913,6 +912,7 @@ namespace Flax.Build.Bindings
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Setup function binding glue to ensure that wrapper method signature matches for C++ and C#
|
||||
functionInfo.Glue = new FunctionInfo.GlueInfo
|
||||
@@ -954,9 +954,22 @@ namespace Flax.Build.Bindings
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
var prevIndent = " ";
|
||||
var indent = " ";
|
||||
contents.Append(prevIndent);
|
||||
#if USE_NETCORE
|
||||
contents.AppendFormat("DLLEXPORT static {0} {1}(", returnValueType, functionInfo.UniqueName);
|
||||
string libraryEntryPoint;
|
||||
if (buildData.Toolchain.Compiler == TargetCompiler.MSVC)
|
||||
libraryEntryPoint = $"{caller.FullNameManaged}::Internal_{functionInfo.UniqueName}"; // MSVC allows to override exported symbol name
|
||||
else
|
||||
libraryEntryPoint = CppNameMangling.MangleFunctionName(buildData, functionInfo.Name, callerName + "Internal", functionInfo.Parameters, functionInfo.Glue.CustomParameters);
|
||||
functionInfo.Glue.LibraryEntryPoint = libraryEntryPoint;
|
||||
#else
|
||||
contents.AppendFormat("static {0} {1}(", returnValueType, functionInfo.UniqueName);
|
||||
#endif
|
||||
CppInternalCalls.Add(new KeyValuePair<string, string>(functionInfo.UniqueName, functionInfo.UniqueName));
|
||||
contents.AppendFormat(" static {0} {1}(", returnValueType, functionInfo.UniqueName);
|
||||
|
||||
var separator = false;
|
||||
if (!functionInfo.IsStatic)
|
||||
@@ -1054,14 +1067,15 @@ namespace Flax.Build.Bindings
|
||||
|
||||
contents.Append(')');
|
||||
contents.AppendLine();
|
||||
contents.AppendLine(" {");
|
||||
contents.Append(prevIndent).AppendLine("{");
|
||||
#if USE_NETCORE
|
||||
contents.AppendLine(string.Format(" SCRIPTING_EXPORT(\"{0}\")", caller.FullNameManaged + "::Internal_" + functionInfo.UniqueName));
|
||||
if (buildData.Toolchain.Compiler == TargetCompiler.MSVC)
|
||||
contents.Append(indent).AppendLine($"MSVC_FUNC_EXPORT(\"{libraryEntryPoint}\")"); // Export generated function binding under the C# name
|
||||
#endif
|
||||
if (!functionInfo.IsStatic)
|
||||
contents.AppendLine(" if (obj == nullptr) DebugLog::ThrowNullReference();");
|
||||
contents.Append(indent).AppendLine("if (obj == nullptr) DebugLog::ThrowNullReference();");
|
||||
|
||||
string callBegin = " ";
|
||||
string callBegin = indent;
|
||||
if (functionInfo.Glue.UseReferenceForResult)
|
||||
{
|
||||
callBegin += "*__resultAsRef = ";
|
||||
@@ -1078,7 +1092,7 @@ namespace Flax.Build.Bindings
|
||||
string callReturnCount = "";
|
||||
if (returnTypeIsContainer)
|
||||
{
|
||||
callReturnCount = " ";
|
||||
callReturnCount = indent;
|
||||
if (functionInfo.ReturnType.Type == "Span" || functionInfo.ReturnType.Type == "BytesContainer")
|
||||
callReturnCount += "*__returnCount = {0}.Length();";
|
||||
else
|
||||
@@ -1132,9 +1146,9 @@ namespace Flax.Build.Bindings
|
||||
if (apiType != null)
|
||||
{
|
||||
if (parameterInfo.IsOut)
|
||||
contents.AppendFormat(" {1} {0}Temp;", parameterInfo.Name, new TypeInfo(parameterInfo.Type) { IsRef = false }.GetFullNameNative(buildData, caller)).AppendLine();
|
||||
contents.Append(indent).AppendFormat("{1} {0}Temp;", parameterInfo.Name, new TypeInfo(parameterInfo.Type) { IsRef = false }.GetFullNameNative(buildData, caller)).AppendLine();
|
||||
else
|
||||
contents.AppendFormat(" auto {0}Temp = {1};", parameterInfo.Name, param).AppendLine();
|
||||
contents.Append(indent).AppendFormat("auto {0}Temp = {1};", parameterInfo.Name, param).AppendLine();
|
||||
if (parameterInfo.Type.IsPtr && !parameterInfo.Type.IsRef)
|
||||
callParams += "&";
|
||||
callParams += parameterInfo.Name;
|
||||
@@ -1143,7 +1157,7 @@ namespace Flax.Build.Bindings
|
||||
// BytesContainer
|
||||
else if (parameterInfo.Type.Type == "BytesContainer" && parameterInfo.Type.GenericArgs == null)
|
||||
{
|
||||
contents.AppendFormat(" BytesContainer {0}Temp;", parameterInfo.Name).AppendLine();
|
||||
contents.Append(indent).AppendFormat("BytesContainer {0}Temp;", parameterInfo.Name).AppendLine();
|
||||
callParams += parameterInfo.Name;
|
||||
callParams += "Temp";
|
||||
}
|
||||
@@ -1151,7 +1165,7 @@ namespace Flax.Build.Bindings
|
||||
// Special case for parameter that cannot be passed directly to the function from the wrapper method input parameter (eg. MonoArray* converted into BytesContainer uses as BytesContainer&)
|
||||
else if (CppParamsThatNeedLocalVariable[i])
|
||||
{
|
||||
contents.AppendFormat(" auto {0}Temp = {1};", parameterInfo.Name, param).AppendLine();
|
||||
contents.Append(indent).AppendFormat("auto {0}Temp = {1};", parameterInfo.Name, param).AppendLine();
|
||||
if (parameterInfo.Type.IsPtr)
|
||||
callParams += "&";
|
||||
callParams += parameterInfo.Name;
|
||||
@@ -1166,7 +1180,7 @@ namespace Flax.Build.Bindings
|
||||
#if USE_NETCORE
|
||||
if (!string.IsNullOrEmpty(callReturnCount))
|
||||
{
|
||||
contents.Append(" ").Append("const auto& __callTemp = ").Append(string.Format(callFormat, call, callParams)).Append(";").AppendLine();
|
||||
contents.Append(indent).Append("const auto& __callTemp = ").Append(string.Format(callFormat, call, callParams)).Append(";").AppendLine();
|
||||
call = "__callTemp";
|
||||
contents.Append(string.Format(callReturnCount, call));
|
||||
contents.AppendLine();
|
||||
@@ -1210,11 +1224,11 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
if (apiType.IsClass)
|
||||
{
|
||||
contents.AppendFormat(" mono_gc_wbarrier_generic_store({0}, (MonoObject*){1});", parameterInfo.Name, value).AppendLine();
|
||||
contents.Append(indent).AppendFormat("mono_gc_wbarrier_generic_store({0}, (MonoObject*){1});", parameterInfo.Name, value).AppendLine();
|
||||
#if USE_NETCORE
|
||||
if (parameterInfo.Type.Type == "Array")
|
||||
{
|
||||
contents.AppendFormat(" *__{0}Count = {1}.Count();", parameterInfo.Name, parameterInfo.Name + "Temp").AppendLine();
|
||||
contents.Append(indent).AppendFormat("*__{0}Count = {1}.Count();", parameterInfo.Name, parameterInfo.Name + "Temp").AppendLine();
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
@@ -1222,7 +1236,7 @@ namespace Flax.Build.Bindings
|
||||
if (apiType.IsStruct && !apiType.IsPod)
|
||||
{
|
||||
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
|
||||
contents.AppendFormat(" {{ auto __temp = {1}; mono_gc_wbarrier_value_copy({0}, &__temp, 1, {2}::TypeInitializer.GetType().ManagedClass->GetNative()); }}", parameterInfo.Name, value, apiType.FullNameNative).AppendLine();
|
||||
contents.Append(indent).AppendFormat("{{ auto __temp = {1}; mono_gc_wbarrier_value_copy({0}, &__temp, 1, {2}::TypeInitializer.GetType().ManagedClass->GetNative()); }}", parameterInfo.Name, value, apiType.FullNameNative).AppendLine();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1231,25 +1245,25 @@ namespace Flax.Build.Bindings
|
||||
// BytesContainer
|
||||
if (parameterInfo.Type.Type == "BytesContainer" && parameterInfo.Type.GenericArgs == null)
|
||||
{
|
||||
contents.AppendFormat(" mono_gc_wbarrier_generic_store({0}, (MonoObject*){1});", parameterInfo.Name, value).AppendLine();
|
||||
contents.AppendFormat(" *__{0}Count = {1}.Length();", parameterInfo.Name, parameterInfo.Name + "Temp").AppendLine();
|
||||
contents.Append(indent).AppendFormat("mono_gc_wbarrier_generic_store({0}, (MonoObject*){1});", parameterInfo.Name, value).AppendLine();
|
||||
contents.Append(indent).AppendFormat("*__{0}Count = {1}.Length();", parameterInfo.Name, parameterInfo.Name + "Temp").AppendLine();
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new Exception($"Unsupported type of parameter '{parameterInfo}' in method '{functionInfo}' to be passed using 'out'");
|
||||
}
|
||||
}
|
||||
contents.AppendFormat(" *{0} = {1};", parameterInfo.Name, value).AppendLine();
|
||||
contents.Append(indent).AppendFormat("*{0} = {1};", parameterInfo.Name, value).AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!useInlinedReturn && !functionInfo.Glue.UseReferenceForResult && !functionInfo.ReturnType.IsVoid)
|
||||
{
|
||||
contents.Append(" return __result;").AppendLine();
|
||||
contents.Append(indent).Append("return __result;").AppendLine();
|
||||
}
|
||||
|
||||
contents.AppendLine(" }");
|
||||
contents.Append(prevIndent).AppendLine("}");
|
||||
contents.AppendLine();
|
||||
}
|
||||
|
||||
@@ -1901,14 +1915,13 @@ namespace Flax.Build.Bindings
|
||||
|
||||
// C# event wrapper binding method (binds/unbinds C# wrapper to C++ delegate)
|
||||
CppInternalCalls.Add(new KeyValuePair<string, string>(eventInfo.Name + "_Bind", eventInfo.Name + "_ManagedBind"));
|
||||
contents.AppendFormat(" static void {0}_ManagedBind(", eventInfo.Name);
|
||||
contents.AppendFormat(" DLLEXPORT static void {0}_ManagedBind(", eventInfo.Name);
|
||||
if (!eventInfo.IsStatic)
|
||||
contents.AppendFormat("{0}* obj, ", classTypeNameNative);
|
||||
contents.Append("bool bind)").AppendLine();
|
||||
contents.Append(" {").AppendLine();
|
||||
#if USE_NETCORE
|
||||
contents.AppendLine(string.Format(" SCRIPTING_EXPORT(\"{0}\")", classTypeNameManagedInternalCall + "::Internal_" + eventInfo.Name + "_Bind"));
|
||||
#endif
|
||||
if (buildData.Toolchain.Compiler == TargetCompiler.MSVC)
|
||||
contents.AppendLine($" MSVC_FUNC_EXPORT(\"{classTypeNameManaged}::Internal_{eventInfo.Name}_Bind\")"); // Export generated function binding under the C# name
|
||||
contents.Append(" Function<void(");
|
||||
for (var i = 0; i < paramsCount; i++)
|
||||
{
|
||||
@@ -1985,14 +1998,14 @@ namespace Flax.Build.Bindings
|
||||
if (!useScripting || !useCSharp || fieldInfo.IsHidden || fieldInfo.IsConstexpr)
|
||||
continue;
|
||||
if (fieldInfo.Getter != null)
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, fieldInfo.Getter, "{0}");
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, classTypeNameInternal, fieldInfo.Getter, "{0}");
|
||||
if (fieldInfo.Setter != null)
|
||||
{
|
||||
var callFormat = "{0} = {1}";
|
||||
var type = fieldInfo.Setter.Parameters[0].Type;
|
||||
if (type.IsArray)
|
||||
callFormat = $"auto __tmp = {{1}}; for (int32 i = 0; i < {type.ArraySize}; i++) {{0}}[i] = __tmp[i]";
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, fieldInfo.Setter, callFormat);
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, classTypeNameInternal, fieldInfo.Setter, callFormat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2002,9 +2015,9 @@ namespace Flax.Build.Bindings
|
||||
if (!useScripting || !useCSharp || propertyInfo.IsHidden)
|
||||
continue;
|
||||
if (propertyInfo.Getter != null)
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, propertyInfo.Getter);
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, classTypeNameInternal, propertyInfo.Getter);
|
||||
if (propertyInfo.Setter != null)
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, propertyInfo.Setter);
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, classTypeNameInternal, propertyInfo.Setter);
|
||||
}
|
||||
|
||||
// Functions
|
||||
@@ -2014,7 +2027,7 @@ namespace Flax.Build.Bindings
|
||||
continue;
|
||||
if (!useScripting)
|
||||
throw new Exception($"Not supported function {functionInfo.Name} inside non-static and non-scripting class type {classInfo.Name}.");
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, functionInfo);
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, classTypeNameInternal, functionInfo);
|
||||
}
|
||||
|
||||
// Interface implementation
|
||||
@@ -2028,7 +2041,7 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
if (!classInfo.IsScriptingObject)
|
||||
throw new Exception($"Class {classInfo.Name} cannot implement interface {interfaceInfo.Name} because it requires ScriptingObject as a base class.");
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, functionInfo);
|
||||
GenerateCppWrapperFunction(buildData, contents, classInfo, classTypeNameInternal, functionInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2184,9 +2197,9 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
|
||||
if (fieldInfo.Getter != null)
|
||||
GenerateCppWrapperFunction(buildData, contents, structureInfo, fieldInfo.Getter, "{0}");
|
||||
GenerateCppWrapperFunction(buildData, contents, structureInfo, structureTypeNameInternal, fieldInfo.Getter, "{0}");
|
||||
if (fieldInfo.Setter != null)
|
||||
GenerateCppWrapperFunction(buildData, contents, structureInfo, fieldInfo.Setter, "{0} = {1}");
|
||||
GenerateCppWrapperFunction(buildData, contents, structureInfo, structureTypeNameInternal, fieldInfo.Setter, "{0} = {1}");
|
||||
}
|
||||
|
||||
// Functions
|
||||
@@ -2194,7 +2207,7 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
// TODO: add support for API functions in structures
|
||||
throw new NotImplementedException($"TODO: add support for API functions in structures (function {functionInfo} in structure {structureInfo.Name})");
|
||||
//GenerateCppWrapperFunction(buildData, contents, structureInfo, functionInfo);
|
||||
//GenerateCppWrapperFunction(buildData, contents, structureInfo, structureTypeNameInternal, functionInfo);
|
||||
}
|
||||
|
||||
GenerateCppTypeInternals?.Invoke(buildData, structureInfo, contents);
|
||||
@@ -2677,8 +2690,6 @@ namespace Flax.Build.Bindings
|
||||
header.Append(" return result;").AppendLine();
|
||||
header.Append('}').AppendLine();
|
||||
header.AppendLine("}");
|
||||
|
||||
PutStringBuilder(header);
|
||||
}
|
||||
|
||||
// Non-POD types
|
||||
@@ -2968,6 +2979,8 @@ namespace Flax.Build.Bindings
|
||||
foreach (var path in CppIncludeFilesList)
|
||||
header.AppendFormat("#include \"{0}\"", path).AppendLine();
|
||||
contents.Insert(headerPos, header.ToString());
|
||||
|
||||
PutStringBuilder(header);
|
||||
}
|
||||
|
||||
contents.AppendLine("PRAGMA_ENABLE_DEPRECATION_WARNINGS");
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Flax.Build.Bindings
|
||||
|
||||
private static List<StringBuilder> _strignBuilderCache;
|
||||
|
||||
private static StringBuilder GetStringBuilder()
|
||||
public static StringBuilder GetStringBuilder()
|
||||
{
|
||||
if (_strignBuilderCache == null || _strignBuilderCache.Count == 0)
|
||||
return new StringBuilder();
|
||||
@@ -73,7 +73,7 @@ namespace Flax.Build.Bindings
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void PutStringBuilder(StringBuilder value)
|
||||
public static void PutStringBuilder(StringBuilder value)
|
||||
{
|
||||
if (_strignBuilderCache == null)
|
||||
_strignBuilderCache = new List<StringBuilder>();
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace Flax.Build.Bindings
|
||||
public struct GlueInfo
|
||||
{
|
||||
public bool UseReferenceForResult;
|
||||
public string LibraryEntryPoint;
|
||||
public List<ParameterInfo> CustomParameters;
|
||||
}
|
||||
|
||||
|
||||
55
Source/Tools/Flax.Build/Utilities/CppNameMangling.cs
Normal file
55
Source/Tools/Flax.Build/Utilities/CppNameMangling.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Flax.Build.Bindings;
|
||||
|
||||
namespace Flax.Build
|
||||
{
|
||||
/// <summary>
|
||||
/// The utilities for C++ typename mangling.
|
||||
/// </summary>
|
||||
internal static class CppNameMangling
|
||||
{
|
||||
public static string MangleFunctionName(Builder.BuildData buildData, string name, string outerName, List<FunctionInfo.ParameterInfo> parameters1, List<FunctionInfo.ParameterInfo> parameters2)
|
||||
{
|
||||
if (parameters1 == null || parameters1.Count == 0)
|
||||
return MangleFunctionName(buildData, name, outerName, parameters2);
|
||||
if (parameters2 == null || parameters2.Count == 0)
|
||||
return MangleFunctionName(buildData, name, outerName, parameters1);
|
||||
var parameters = new List<FunctionInfo.ParameterInfo>();
|
||||
parameters.AddRange(parameters1);
|
||||
parameters.AddRange(parameters2);
|
||||
return MangleFunctionName(buildData, name, outerName, parameters);
|
||||
}
|
||||
|
||||
public static string MangleFunctionName(Builder.BuildData buildData, string name, string outerName, List<FunctionInfo.ParameterInfo> parameters)
|
||||
{
|
||||
if (name.Contains(":"))
|
||||
throw new NotImplementedException("No nested types mangling support.");
|
||||
var sb = BindingsGenerator.GetStringBuilder();
|
||||
switch (buildData.Toolchain.Compiler)
|
||||
{
|
||||
case TargetCompiler.MSVC:
|
||||
// References:
|
||||
// https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names
|
||||
// https://mearie.org/documents/mscmangle/
|
||||
sb.Append('?');
|
||||
sb.Append(name);
|
||||
sb.Append('@');
|
||||
sb.Append(outerName);
|
||||
sb.Append('@');
|
||||
// TODO: mangle parameters
|
||||
break;
|
||||
case TargetCompiler.Clang:
|
||||
sb.Append("todo");
|
||||
break;
|
||||
default:
|
||||
throw new InvalidPlatformException(buildData.Platform.Target);
|
||||
}
|
||||
var result = sb.ToString();
|
||||
BindingsGenerator.PutStringBuilder(sb);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user