1

From C#.NET I'm trying to PInvoke a method from a C++ assembly (no access to source) with this signature

result_code get_values(values_report_type *values_report)

Where values_report is a pointer to a struct of values_report_type containing the values I am querying which are returned by the method. The struct looks like this:

typedef struct{
    int countOfValues;
    values_type* values;
    const char* name;
} values_report_type;

Where values is an array of struct values_type.

Here's what I would assume to be the problem: the C++ assembly I am working against gives me no information about the content of the values_type struct other than the definition

typedef struct values_type_struct *values_type

According to documentation this privacy is intentional.

So, my C# PInvoke looks like this right now:

[DllImport("MyLibrary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
internal static extern result_code get_values(out values_report_type values_report);

internal struct values_report_type{
    int countOfValues;
    IntPtr values;
    string name;
}

That works fine and gives me a pointer to the values struct, but what I need is to access the array of values_type structs and get a pointer to each of the items in the array (a pointer to each item is all I need since I don't have a definition for the struct contents). But I can't think of a way to achieve this, especially because the library has limited me in what it says about that struct (not even giving length). In C++ it would just be something like values_report.values[0] and so on for each item as defined by countOfValues, but I don't know of a way to make it work when marshalling it to .NET.

Is there a way to solve this in C# via marshalling?

12
  • values is not an array of struct. It is an array of pointers to struct values_type_struct. What are you meant to do with the elements in values? Reading values[i] is easy enough (IntPtr Value = Marshal.ReadIntPtr(values_report.values, i*IntPtr.Size)), it's what happens next that is not clear. Commented Jan 10, 2017 at 11:18
  • I worked a long time on unix operating systems and have read the entire UNIX manual a number of times. Any structure/array you must be able to determine where each record ends. Either by a fixed size object, a length property in the structure, or a terminating character like '\0'.Your structure is all fixed size objects so if you want an array then simply have one structure follow another in memory followed by a '\0'. The only issue is when countOfValues is zero it will look like a '\0'.So at the beginning of the array you may want to add an integer of the number of arrays you are sending. Commented Jan 10, 2017 at 11:22
  • @DavidHeffernan There are more methods in the SDK that use the pointer to the values_type_struct elements to perform calculations. So basically, I can't view the contents of the struct but I can send a pointer to it to another method for calculations and transformation. Commented Jan 10, 2017 at 11:23
  • 1
    That sounds right. If so, then it is what is known as an opaque pointer. In that case I think you have what you need now. Commented Jan 10, 2017 at 11:25
  • The best solution I can think of would be to try and generate an array of values_type objects by converting it to a byte array using Marshal.Copy then feeding it into a BinarySerializer. The only problem is that in order to do the marshalling, you would need to know the size of the amount of memory you want to get, so you will need to know the size of the array (presumably given by countOfValues) as well as the size of a values_type object (less obvious). Commented Jan 10, 2017 at 11:27

1 Answer 1

2

values is not an array of struct. It is an array of pointers to struct.

Based on the comments, and looking at the code, it seems that you don't have a definition of the struct itself. This is what is known as an opaque pointer. You don't need to know the struct size, you just deal in the pointer to the struct, passing that back to the library.

Read the opaque pointer values from the array like this:

IntPtr Value = Marshal.ReadIntPtr(values_report.values, i*IntPtr.Size);

This obtains the ith value.

Sign up to request clarification or add additional context in comments.

3 Comments

I may have missed something, but I'm not seeing where values is an array of struct pointers. I just see it being of type values_type*. Now my C/C++ is a bit rudimentary, but I take that to mean a pointer to a single values_type, which can alternatively be used to mean an array of values_types. Would an array of pointers not be represented by values_type**?
typedef struct values_type_struct *values_type. So values_type is pointer to struct.
Ah, I see. I'm not used to looking for typedefs. :P

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.