Nihlus/AdvancedDLSupport

Implement a way to marshal arrays as return types

Nihlus opened this issue · 5 comments

Typically, arrays cannot be automatically marshalled as return types from native code, due to them being raw pointers without range information. This is a limitation in traditional P/Invoke, and one that is not usually solved on a binding level.

Describe the solution you'd like
Having ADL support a scenario where the length of an array could be retrieved from another member of the same type (a method, or a property) and then used to marshal the return pointer would be an interesting and useful solution to the problem.

Conceivably, an attribute such as [LengthSource(string memberName)] could be provided, which when applied to a return parameter would invoke or read the given member in order to retrieve the length of the array in question. As an example,

interface ILibrary
{
    UIntPtr GetNumNames();

    [return: LengthSource(nameof(GetNumNames))]
    string[] GetNames();
}

would be valid syntax.

The signature of the length retrieval method would be limited to predictable scenarios; initially, only parameterless methods returning a numeric type would be considered valid. Methods that do not fit the constraints would result in a bind-time exception.

The same would hold for properties - numeric properties only, and an accessible getter must be present.

Describe alternatives you've considered
At the moment, alternative options is to implement this type of behaviour yourself in a mixed-mode class.

Additional context
OpenTK would benefit from this features, as it has a number of signatures following this pattern.

[return: LengthSource(nameof(GetNumNames)]

Missing another closing parenthesis.

Fixed, thanks.

Returning arrays would require an explicit copy, there is no safe way to encapsulate the data from unmanaged code without copying it, whereas Span<> removes the need of the copy, hence it's use

Could this be closed as we have a pretty close equivalent (#76), or do we still want arrays? In my opinion, spans do just fine in most cases.

Yes - spans are far more useful and representative of unmanaged memory, and can be converted to arrays in user code.