From 4307fb3303cb69d2d94c5aefadc63df0b6b8a58e Mon Sep 17 00:00:00 2001 From: realvictorprm Date: Thu, 16 Mar 2017 21:15:59 +0100 Subject: [PATCH] Fixed ArgumentException due to nullptr arguments in Marshaling native function pointers. (#794) --- src/Generator/Generators/CLI/CLIMarshal.cs | 2 +- src/Generator/Generators/CSharp/CSharpMarshal.cs | 6 +++--- tests/Common/Common.Tests.cs | 3 +++ tests/Common/Common.cpp | 5 +++++ tests/Common/Common.h | 3 +++ 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 127d9cff..4ecfdf96 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -249,7 +249,7 @@ namespace CppSharp.Generators.CLI FunctionType function; if (decl.Type.IsPointerTo(out function)) { - Context.Return.Write("safe_cast<{0}>(", typedef); + Context.Return.Write($"{Context.ReturnVarName} == nullptr ? nullptr : safe_cast<{typedef}>("); Context.Return.Write("System::Runtime::InteropServices::Marshal::"); Context.Return.Write("GetDelegateForFunctionPointer("); Context.Return.Write("IntPtr({0}), {1}::typeid))",Context.ReturnVarName, diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index df680da4..458a1f4f 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -249,9 +249,9 @@ namespace CppSharp.Generators.CSharp Context.SupportBefore.WriteLine("var {0} = {1};", ptrName, Context.ReturnVarName); - - Context.Return.Write("({1})Marshal.GetDelegateForFunctionPointer({0}, typeof({1}))", - ptrName, typedef.ToString()); + + var res = $"{ptrName} == IntPtr.Zero? null : ({typedef})Marshal.GetDelegateForFunctionPointer({ptrName}, typeof({typedef}))"; + Context.Return.Write(res); return true; } diff --git a/tests/Common/Common.Tests.cs b/tests/Common/Common.Tests.cs index 30049391..06f2a00c 100644 --- a/tests/Common/Common.Tests.cs +++ b/tests/Common/Common.Tests.cs @@ -317,6 +317,9 @@ public class CommonTests : GeneratorTestFixture var cdecl = delegates.CDecl(i => i); Assert.AreEqual(1, cdecl); + + var emptydelegeate = delegates.MarshalNullDelegate; + Assert.AreEqual(emptydelegeate, null); } [Test] diff --git a/tests/Common/Common.cpp b/tests/Common/Common.cpp index 29229db9..02657bce 100644 --- a/tests/Common/Common.cpp +++ b/tests/Common/Common.cpp @@ -421,6 +421,11 @@ void TestDelegates::MarshalDelegateInAnotherUnit(DelegateInAnotherUnit del) { } +DelegateNullCheck TestDelegates::MarshalNullDelegate() +{ + return nullptr; +} + void DelegateNamespace::f2(void (*)()) { } diff --git a/tests/Common/Common.h b/tests/Common/Common.h index 54cc9a82..bf50f333 100644 --- a/tests/Common/Common.h +++ b/tests/Common/Common.h @@ -324,6 +324,7 @@ DLL_API int operator==(const Foo2& a, const Foo2& b) typedef int (*DelegateInGlobalNamespace)(int); typedef int (STDCALL *DelegateStdCall)(int); typedef int (CDECL *DelegateCDecl)(int n); +typedef void(*DelegateNullCheck)(void); struct DLL_API TestDelegates { @@ -345,6 +346,8 @@ struct DLL_API TestDelegates void MarshalDelegateInAnotherUnit(DelegateInAnotherUnit del); + DelegateNullCheck MarshalNullDelegate(); + DelegateInClass A; DelegateInGlobalNamespace B; // As long as we can't marshal them make sure they're ignored