Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable ROS2 initialization arguments and perhaps native subdirectory path library loading? #134

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions rcldotnet/RCLdotnet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1470,14 +1470,29 @@ public static void SpinOnce(Node node, long timeout)
}
}

/// <summary>
/// Initialize ROS2 with app's launch arguments.
/// </summary>
public static void Init()
{
string[] args = System.Environment.GetCommandLineArgs();
Init(args);
}

/// <summary>
/// Initialize ROS2 with supplied arguments.
/// </summary>
/// <remarks>
/// This is overloaded so that it can support arguments set up during run-time.
/// </remarks>
/// <param name="args">ROS2 arguments to pass along.</param>
public static void Init(string[] args)
{
lock (syncLock)
{
if (!initialized)
{
string[] args = System.Environment.GetCommandLineArgs();
RCLRet ret = RCLdotnetDelegates.native_rcl_init(args.Length, args);
RCLRet ret = RCLdotnetDelegates.native_rcl_init(args.Length, args.Length <= 0 ? null : args);
RCLExceptionHelper.CheckReturnValue(ret, $"{nameof(RCLdotnetDelegates.native_rcl_init)}() failed.");
initialized = true;
}
Expand Down
14 changes: 10 additions & 4 deletions rcldotnet_common/DllLoadUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
// Based on http://dimitry-i.blogspot.com.es/2013/01/mononet-how-to-dynamically-load-native.html

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace ROS2
Expand Down Expand Up @@ -195,6 +196,8 @@ public void RegisterNativeFunction<FunctionType>(IntPtr nativeLibrary, string na
IntPtr nativeFunctionPointer = GetProcAddress(nativeLibrary, nativeFunctionName);
functionDelegate = (FunctionType)Marshal.GetDelegateForFunctionPointer(nativeFunctionPointer, typeof(FunctionType));
}

public const string AssemblyDirectory = "ros2";
}

public class DllLoadUtilsUWP : DllLoadUtilsAbs
Expand All @@ -215,7 +218,7 @@ public class DllLoadUtilsUWP : DllLoadUtilsAbs

public override IntPtr LoadLibrary(string fileName)
{
string libraryName = fileName + "_native.dll";
string libraryName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AssemblyDirectory, fileName + "_native.dll");
IntPtr ptr = LoadPackagedLibraryUWP(libraryName);
if (ptr == IntPtr.Zero)
{
Expand All @@ -228,6 +231,9 @@ public override IntPtr LoadLibrary(string fileName)
public class DllLoadUtilsWindowsDesktop : DllLoadUtilsAbs
{

[DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = true, ExactSpelling = true)]
private static extern int GetLastError();

[DllImport("kernel32.dll", EntryPoint = "LoadLibraryA", SetLastError = true, ExactSpelling = true)]
private static extern IntPtr LoadLibraryA(string fileName, int reserved = 0);

Expand All @@ -243,7 +249,7 @@ public class DllLoadUtilsWindowsDesktop : DllLoadUtilsAbs

public override IntPtr LoadLibrary(string fileName)
{
string libraryName = fileName + "_native.dll";
string libraryName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AssemblyDirectory, fileName + "_native.dll");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO this is a bit of a patch.
The search path should not be set to a hard path, as you cannot change the path of the library now. it is better to use the "AddDllDirectory" function. https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-adddlldirectory.
This is also the recommended solution from microsoft in the LoadLibraryA function https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about the UWP part? I haven't found any recommendation on loading from sub-directory in UWP.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like there is no "addDllDirectory" for UWP. but following the microsoft documentation it says that you need to add the path to the packagedepency in the application package manifest https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-loadpackagedlibrary

IntPtr ptr = LoadLibraryA(libraryName);
if (ptr == IntPtr.Zero)
{
Expand Down Expand Up @@ -287,7 +293,7 @@ public override IntPtr GetProcAddress(IntPtr dllHandle, string name)

public override IntPtr LoadLibrary(string fileName)
{
string libraryName = "lib" + fileName + "_native.so";
string libraryName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AssemblyDirectory, "lib" + fileName + "_native.so");
IntPtr ptr = dlopen(libraryName, RTLD_NOW);
if (ptr == IntPtr.Zero)
{
Expand Down Expand Up @@ -334,7 +340,7 @@ public override IntPtr GetProcAddress(IntPtr dllHandle, string name)

public override IntPtr LoadLibrary(string fileName)
{
string libraryName = "lib" + fileName + "_native.dylib";
string libraryName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AssemblyDirectory, "lib" + fileName + "_native.dylib");
IntPtr ptr = dlopen(libraryName, RTLD_NOW);
if (ptr == IntPtr.Zero)
{
Expand Down