question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[DllImport] Improve pinvoke for `GetDroppedFiles()` and similar.

See original GitHub issue

Before submitting a new issue, please verify and check:

  • [x ] The issue is specific to Raylib-cs and not raylib
  • [ x] I checked there is no similar issue already reported
  • [ x] My code has no errors or misuse of Raylib-cs

Issue description

In raylib.h the definition is:

RLAPI char **GetDroppedFiles(int *count);  

Currently in raylib-cs the following is used:

        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr GetDroppedFiles(ref int count);

I suggest using a call more precicely matching raylib, plus a wrapper to make it easier for C# devs to use, as otherwise the C# dev needs to do this wrapper themselves.

[DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
public static extern byte** GetDroppedFiles(int* count);

public static ReadOnlySpan<string> GetDroppedFiles()
{
    int count;
    var buffer = GetDroppedFiles(&count);
    var files  = new string[count];

    for (int i = 0; i < count; i++)
    {
        files[i] = Marshal.PtrToStringUTF8((IntPtr)buffer[i]);
    }

    return files;
}

Environment

N/A Win10 x64, dotnet6

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
DaZombieKillercommented, Oct 21, 2021

Not sure about returning ReadOnlySpan though.

Yeah, it might be better if it just returned a string[] directly. It would make it more obvious that it’s an allocating API, and you can always assign the result to a ReadOnlySpan<string> yourself. Ideally, Raylib would have an additional GetDroppedFilesCount API (assuming multiple calls to GetDroppedFiles aren’t allowed), so you could preallocate a buffer yourself and have the API write into it (which would be translated into something like a Span<string> parameter in the C# binding, or something like Span<Utf8CString> where Utf8CString is just a struct wrapping a byte* if you wanted absolutely minimal allocations.)

There is also the option of using the Utf8CString concept with the existing API:

[DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
public static extern byte** GetDroppedFiles(int* count);

public static ReadOnlySpan<Utf8CString> GetDroppedFiles()
{
    int count;
    var buffer = GetDroppedFiles(&count);
    return new(buffer, count);
}

// Minimal implementation, real deal would have more code
// to make it more convenient to work with alongside "string"
public readonly struct Utf8CString
{
    readonly byte* address;
    public override string ToString() => Marshal.PtrToStringUTF8((IntPtr)address);
}
0reactions
jasonswearingencommented, Dec 4, 2021

I think that requiring the user to write glue code is the best “smell test”. so in your or the examples use of raylib, if there are areas that need similar workflows. Though I don’t think there are many like that. I think the biggest pain was needing to cast everything to IntPtr which seems to be resolved in the 4.0 changes!

Read more comments on GitHub >

github_iconTop Results From Across the Web

P/Invoke (DLLImport) Different Function Signature
I tried putting in a different function signature that I know should not have worked. Original: int Foo(LibraryDefinedString str, _Outptr_ ...
Read more >
Native interoperability best practices - .NET
CONSIDER wrapping your P/Invoke declarations in a class with the same name and capitalization as your native library.
Read more >
Platform Invoke (P/Invoke)
Line #8 introduces the DllImport attribute. This attribute tells the runtime that it should load the unmanaged DLL. The string passed in is...
Read more >
DllImport cross-platform best practices? · Issue #8295
Hi, I would like to connect to my Canon DSLR camera on Windows and Mac over Canon EDSDK. In Windows, I can use...
Read more >
Migrating existing working P/Invoke from [DllImport] to ...
Only in the sense that a like-for-like function name no longer works. Known Workarounds. Either the user changes the code to add an...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found