Skip to content

Commit 80a70ff

Browse files
Merge pull request #48 from FabianTerhorst/dev
Improve assembly execution and loading
2 parents 324bfa5 + 7f2eb65 commit 80a70ff

File tree

11 files changed

+191
-149
lines changed

11 files changed

+191
-149
lines changed

api/AltV.Net.Async/AltV.Net.Async.csproj

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@
1212
<RepositoryUrl>https://github.com/altmp-csharp/docs</RepositoryUrl>
1313
<RepositoryType>git</RepositoryType>
1414
<PackageTags>altv gta bridge</PackageTags>
15-
<PackageVersion>1.13.1-alpha</PackageVersion>
15+
<PackageVersion>1.13.1</PackageVersion>
1616
<PackageLicenseFile>license.txt</PackageLicenseFile>
17-
<PackageReleaseNotes>Add IScript for automatically loading scripts that contains Events and ScriptEvents
18-
Update dependencies</PackageReleaseNotes>
17+
<PackageReleaseNotes>Fix multi async resources</PackageReleaseNotes>
1918
</PropertyGroup>
2019

2120
<ItemGroup>

api/AltV.Net.Async/AltVAsync.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ internal class AltVAsync
1313
public AltVAsync(ITickSchedulerFactory tickSchedulerFactory)
1414
{
1515
mainThread = Thread.CurrentThread;
16-
mainThread.Name = "main";
16+
if (mainThread.Name == "")
17+
{
18+
mainThread.Name = "main";
19+
}
20+
1721
scheduler = tickSchedulerFactory.Create(mainThread);
1822
taskFactory = new TaskFactory(
1923
CancellationToken.None, TaskCreationOptions.DenyChildAttach,

api/AltV.Net.Example/AltV.Net.Example.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
</ItemGroup>
3232

3333
<ItemGroup>
34-
<PackageReference Include="MySqlConnector" Version="0.49.3" />
34+
<PackageReference Include="MySql.Data" Version="8.0.17" />
35+
<PackageReference Include="System.Data.SqlClient" Version="4.7.0-preview8.19405.3" />
3536
</ItemGroup>
3637

3738
<Target Name="CopyFiles" AfterTargets="build">

api/AltV.Net.Host/Host.cs

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,56 @@
33
using System.IO;
44
using System.Reflection;
55
using System.Runtime.InteropServices;
6+
using System.Threading;
67

78
namespace AltV.Net.Host
89
{
910
public class Host
1011
{
11-
private static IDictionary<string, ResourceAssemblyLoadContext> _loadContexts =
12+
private static readonly IDictionary<string, ResourceAssemblyLoadContext> _loadContexts =
1213
new Dictionary<string, ResourceAssemblyLoadContext>();
1314

15+
private const string DllName = "csharp-module";
16+
private const CallingConvention NativeCallingConvention = CallingConvention.Cdecl;
17+
18+
internal delegate int CoreClrDelegate(IntPtr args, int argsLength);
19+
20+
[DllImport(DllName, CallingConvention = NativeCallingConvention)]
21+
internal static extern void CoreClr_SetResourceLoadDelegates(CoreClrDelegate resourceExecute,
22+
CoreClrDelegate resourceExecuteUnload);
23+
24+
private static CoreClrDelegate _executeResource;
25+
26+
private static CoreClrDelegate _executeResourceUnload;
27+
1428
/// <summary>
1529
/// Main is present to execute the dll as a assembly
1630
/// </summary>
17-
static void Main()
31+
static int Main(string[] args)
1832
{
19-
//TODO: init stuff we need
20-
Console.WriteLine("Init host");
33+
var semaphore = new Semaphore(0, 1);
34+
SetDelegates();
35+
semaphore.WaitOne();
36+
return 0;
37+
}
38+
39+
public static int Main2(IntPtr arg, int argLength)
40+
{
41+
SetDelegates();
42+
return 0;
43+
}
44+
45+
private static void SetDelegates()
46+
{
47+
_executeResource = ExecuteResource;
48+
GCHandle.Alloc(_executeResource);
49+
_executeResourceUnload = ExecuteResourceUnload;
50+
GCHandle.Alloc(_executeResourceUnload);
51+
CoreClr_SetResourceLoadDelegates(_executeResource, _executeResourceUnload);
2152
}
2253

2354
private static string GetPath(string resourcePath, string resourceMain) =>
24-
$"{resourcePath}/{resourceMain}";
55+
$"{resourcePath}{Path.DirectorySeparatorChar}{resourceMain}";
2556

2657
[StructLayout(LayoutKind.Sequential)]
2758
public struct LibArgs
@@ -56,6 +87,8 @@ public static int ExecuteResource(IntPtr arg, int argLength)
5687
var resourceAssemblyLoadContext =
5788
new ResourceAssemblyLoadContext(resourceDllPath, resourcePath, resourceName);
5889

90+
_loadContexts[resourceDllPath] = resourceAssemblyLoadContext;
91+
5992
Assembly resourceAssembly;
6093

6194
try
@@ -65,21 +98,18 @@ public static int ExecuteResource(IntPtr arg, int argLength)
6598
catch (FileLoadException e)
6699
{
67100
Console.WriteLine($"Threw a exception while loading the assembly \"{resourceDllPath}\": {e}");
68-
resourceAssembly = null;
101+
return 1;
69102
}
70103

71104
var altVNetAssembly = resourceAssemblyLoadContext.LoadFromAssemblyName(new AssemblyName("AltV.Net"));
72105
foreach (var type in altVNetAssembly.GetTypes())
73106
{
74-
if (type.Name == "ModuleWrapper")
75-
{
76-
type.GetMethod("MainWithAssembly", BindingFlags.Public | BindingFlags.Static)?.Invoke(null,
77-
new object[] {libArgs.ServerPointer, libArgs.ResourcePointer, resourceAssemblyLoadContext});
78-
}
107+
if (type.Name != "ModuleWrapper") continue;
108+
type.GetMethod("MainWithAssembly", BindingFlags.Public | BindingFlags.Static)?.Invoke(null,
109+
new object[] {libArgs.ServerPointer, libArgs.ResourcePointer, resourceAssemblyLoadContext});
110+
break;
79111
}
80112

81-
_loadContexts[resourceDllPath] = resourceAssemblyLoadContext;
82-
83113
return 0;
84114
}
85115

@@ -97,7 +127,14 @@ public static int ExecuteResourceUnload(IntPtr arg, int argLength)
97127
var resourceDllPath = GetPath(resourcePath, resourceMain);
98128

99129
if (!_loadContexts.Remove(resourceDllPath, out var loadContext)) return 1;
130+
var loadContextWeakReference = new WeakReference(loadContext);
100131
loadContext.Unload();
132+
for (var i = 0; loadContextWeakReference.IsAlive && (i < 10); i++)
133+
{
134+
GC.Collect();
135+
GC.WaitForPendingFinalizers();
136+
}
137+
101138
return 0;
102139
}
103140
}

api/AltV.Net.Host/ResourceAssemblyLoadContext.cs

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,56 +9,51 @@ public class ResourceAssemblyLoadContext : AssemblyLoadContext
99
{
1010
private readonly AssemblyDependencyResolver resolver;
1111

12-
private readonly string resourcePath;
13-
1412
public ResourceAssemblyLoadContext(string resourceDllPath, string resourcePath, string resourceName) : base(resourceName,
1513
true)
1614
{
1715
resolver = new AssemblyDependencyResolver(resourceDllPath);
18-
this.resourcePath = resourcePath;
16+
Resolving += (context, assemblyName) =>
17+
{
18+
var dllPath = resourcePath + Path.DirectorySeparatorChar + assemblyName.Name;
19+
if (!File.Exists(dllPath)) return null;
20+
try
21+
{
22+
return LoadFromAssemblyPath(dllPath);
23+
}
24+
catch (Exception exception)
25+
{
26+
Console.WriteLine(exception);
27+
}
28+
29+
return null;
30+
};
31+
ResolvingUnmanagedDll += (assembly, unmanagedDllName) =>
32+
{
33+
var dllPath = resourcePath + Path.DirectorySeparatorChar + unmanagedDllName;
34+
if (!File.Exists(dllPath)) return IntPtr.Zero;
35+
try
36+
{
37+
return LoadUnmanagedDllFromPath(dllPath);
38+
}
39+
catch (Exception exception)
40+
{
41+
Console.WriteLine(exception);
42+
}
43+
44+
return IntPtr.Zero;
45+
};
1946
}
2047

2148
protected override Assembly Load(AssemblyName assemblyName)
2249
{
2350
var assemblyPath = resolver.ResolveAssemblyToPath(assemblyName);
24-
if (assemblyPath == null)
25-
{
26-
var dllPath = resourcePath + Path.DirectorySeparatorChar + assemblyName.Name;
27-
if (File.Exists(dllPath))
28-
{
29-
try
30-
{
31-
return LoadFromAssemblyPath(dllPath);
32-
}
33-
catch (Exception exception)
34-
{
35-
Console.WriteLine(exception);
36-
}
37-
}
38-
}
3951
return assemblyPath != null ? LoadFromAssemblyPath(assemblyPath) : null;
4052
}
4153

4254
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
4355
{
4456
var libraryPath = resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
45-
46-
if (libraryPath == null)
47-
{
48-
var dllPath = resourcePath + Path.DirectorySeparatorChar + unmanagedDllName;
49-
if (File.Exists(dllPath))
50-
{
51-
try
52-
{
53-
return LoadUnmanagedDllFromPath(dllPath);
54-
}
55-
catch (Exception exception)
56-
{
57-
Console.WriteLine(exception);
58-
}
59-
}
60-
}
61-
6257
return libraryPath != null ? LoadUnmanagedDllFromPath(libraryPath) : IntPtr.Zero;
6358
}
6459
}

api/AltV.Net.Mock/AltV.Net.Mock.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<RepositoryUrl>https://github.com/altmp-csharp/docs</RepositoryUrl>
1212
<RepositoryType>git</RepositoryType>
1313
<PackageTags>altv gta bridge mock</PackageTags>
14-
<PackageVersion>1.13.1-alpha</PackageVersion>
14+
<PackageVersion>1.13.0</PackageVersion>
1515
<PackageLicenseFile>license.txt</PackageLicenseFile>
1616
<PackageReleaseNotes>Update dependencies</PackageReleaseNotes>
1717
</PropertyGroup>

api/AltV.Net/AltV.Net.csproj

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,9 @@
1313
<RepositoryUrl>https://github.com/altmp-csharp/docs</RepositoryUrl>
1414
<RepositoryType>git</RepositoryType>
1515
<PackageTags>altv gta bridge</PackageTags>
16-
<PackageVersion>1.13.1-alpha</PackageVersion>
16+
<PackageVersion>1.13.0</PackageVersion>
1717
<PackageLicenseFile>license.txt</PackageLicenseFile>
18-
<PackageReleaseNotes>Add to IVehicle
19-
```csharp
20-
byte Livery { get; set; }
21-
byte RoofLivery { get; set; }
22-
float LightsMultiplier { get; set; }
23-
```
24-
Add to IServer
25-
```csharp
26-
int NetTime { get; }
27-
```
28-
Improve meta data's
29-
Rewrite entity handling
30-
Add DegreeRotation and optimize position distance calculation</PackageReleaseNotes>
18+
<PackageReleaseNotes></PackageReleaseNotes>
3119
</PropertyGroup>
3220

3321
<ItemGroup>

api/AltV.Net/ModuleWrapper.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.IO;
32
using System.Runtime.CompilerServices;
43
using System.Runtime.Loader;
54
using AltV.Net.Elements.Args;
@@ -46,7 +45,6 @@ public static void MainWithAssembly(IntPtr serverPointer, IntPtr resourcePointer
4645
}
4746

4847
MainWithResource(serverPointer, resourcePointer, resource, assemblyLoadContext);
49-
//TODO: set delegates here
5048
_scripts = AssemblyLoader.FindAllTypes<IScript>(assemblyLoadContext.Assemblies);
5149
_module.OnScriptsLoaded(_scripts);
5250
ResourceBuilder.SetDelegates(resourcePointer, OnStartResource);
@@ -55,7 +53,6 @@ public static void MainWithAssembly(IntPtr serverPointer, IntPtr resourcePointer
5553
public static void MainWithResource(IntPtr serverPointer, IntPtr resourcePointer, IResource resource,
5654
AssemblyLoadContext assemblyLoadContext)
5755
{
58-
Console.WriteLine("before resource:" + (_resource == null));
5956
_resource = resource;
6057
if (_resource == null)
6158
{

runtime/include/CoreClr.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@
1414

1515
#endif
1616

17+
#ifdef _WIN32
18+
19+
#define EXPORT EXTERN __declspec(dllexport)
20+
#define IMPORT EXTERN __declspec(dllimport)
21+
22+
#else
23+
24+
#define EXPORT EXTERN __attribute__ ((visibility ("default")))
25+
#define IMPORT
26+
27+
#endif // _WIN32
28+
1729
#include <coreclr/hostfxr.h>
1830
#include <coreclr/coreclr_delegates.h>
1931

@@ -87,6 +99,10 @@ int tail_gt(char* lhs, char* rhs);
8799
typedef void (* ExecuteResourceDelegate_t)(const char* resourcePath, const char* resourceName, const char* resourceMain,
88100
int resourceIndex);
89101

102+
typedef int (* CoreClrDelegate_t)(void* args, int argsLength);
103+
104+
#include <thread>
105+
90106
class CoreClr {
91107
public:
92108
CoreClr(alt::IServer* server);
@@ -118,22 +134,21 @@ class CoreClr {
118134
*/
119135
bool PrintError(alt::IServer* server, int errorCode);
120136

121-
void CreateManagedHost(alt::IServer* server);
137+
void CreateManagedHost();
122138

123139
void ExecuteManagedResource(alt::IServer* server, const char* resourcePath, const char* resourceName,
124140
const char* resourceMain, alt::IResource* resource);
125141

126142
void ExecuteManagedResourceUnload(alt::IServer* server, const char* resourcePath, const char* resourceMain);
127143

128-
load_assembly_and_get_function_pointer_fn get_dotnet_load_assembly(const char_t* config_path);
129-
130144
private:
131145
#ifdef _WIN32
132146
HMODULE _coreClrLib;
133147
#else
134148
void* _coreClrLib;
135149
#endif
136150
char* runtimeDirectory;
151+
char* dotnetDirectory;
137152
coreclr_initialize_ptr _initializeCoreCLR;
138153
coreclr_shutdown_2_ptr _shutdownCoreCLR;
139154
coreclr_create_delegate_ptr _createDelegate;
@@ -145,5 +160,11 @@ class CoreClr {
145160

146161
hostfxr_initialize_for_runtime_config_fn _initializeFxr;
147162
hostfxr_get_runtime_delegate_fn _getDelegate;
163+
hostfxr_run_app_fn _runApp;
164+
hostfxr_initialize_for_dotnet_command_line_fn _initForCmd;
148165
hostfxr_close_fn _closeFxr;
166+
hostfxr_handle cxt;
167+
std::thread thread;
149168
};
169+
170+
EXPORT void CoreClr_SetResourceLoadDelegates(CoreClrDelegate_t resourceExecute, CoreClrDelegate_t resourceExecuteUnload);

runtime/src/CSharpScriptRuntime.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ CSharpScriptRuntime::CSharpScriptRuntime(alt::IServer* server)
44
{
55
this->server = server;
66
this->coreClr = new CoreClr(server);
7-
this->coreClr->CreateManagedHost(server);
7+
this->coreClr->CreateManagedHost();
88
}
99

1010
alt::IResource *CSharpScriptRuntime::CreateResource(alt::IResource::CreationInfo* info)

0 commit comments

Comments
 (0)