I know this sounds really strange, but I don't know how to even ask this properly. I've been trying to P/Invoke into NVidia's NVML library with limited success: I've managed to call a few of the APIs exported by that library
Now I am trying to call nvmlDeviceGetHandleByIndex_v2 but I've been stuck for a long while on this one. It takes in a nvmlDevice_t pointer, but I've found nothing on what nvmlDevice_t actually is beyond this header definition:
typedef struct nvmlDevice_st* nvmlDevice_t;
The problem is that the header file does not make any other reference to nvmlDevice_st so I don't know how much heap space to allocate for it, if any. I've found this official C++ example that calls that same function like this:
nvmlDevice_t device;
CheckNVMLErrors(nvmlDeviceGetHandleByIndex(device_index, &device));
My main problem is that I'm not familiar enough with C/C++ to understand the implicit mechanics/memory allocation done by the device declaration, and the nvml.h header does not define what nvmlDevice_st actually is.
I tried calling it with a ref int parameter (with an initial 0 value) and apparently it does work but I want to understand why, if possible. For reference, the value of that ref int parameter after the call was 1460391512, in case something can be gleamed off that.
If you look at the source, that is just an internal pointer used by the SDK. The value it points to has no meaning to you. You use it to identify a device you are working with.
Think Handle or HWND in Windows. You call something like FindWindow(), it returns what seems to be a random value back to you. You don't care what that value holds, you just use that value to identify that window when you call GetWindowText() or any other windowing methods.
So, you are on the right track with using ref int, but what you want is a pointer. So you should use out IntPtr to get the value.
Related
I have a function which I can't alter because of protection and abstraction, and it is declared like this:
GetDeviceLongInfo(int, int, ref int);
In which the "ref int" argument to be passed is said to give back 6400 bytes of information.
My question is, how can I get this information in a variable if the only choice I have is to give the function an Int32? Can I allocate more memory for that Int32? Is this even possible to achieve in some way?
EDIT:
I can tell you that the function uses the ref int to dump values in it, the int size (size of the information) is not fixed, depends on the option chosed in the second parameter. I can't even look at the function to see how it uses that ref.
You can allocate an int[] and pass that to the function. This is a hack but I don't see why it should not be safe.
var array = new int[6400 / sizeof(int)];
GetDevice(..., ref array[0]);
The array is pinned by the CLR for the duration of the call.
Note, that ref is a so called managed pointer to the CLR. It is marshaled by passing it as a pointer and pinning the object it points to. An int[] would be passed in almost the same way (a pointer to the first element is passed).
Can I allocate more memory for that Int32? No
Is this even possible to achieve in some way? Changing the signature or using the int as a reference to the data are both options
You're attempting to marshal an array (which is a native pointer to data) to an integer. C# will have no problem with that, but processing it is another story. Also note that depending on your architecture you will have different pointer sizes, which means using a 32-bit int isn't the way to go.
See also: http://msdn.microsoft.com/en-us/library/z6cfh6e6(v=vs.110).aspx
I cannot remember the details from the top of my head, but basically you want to use the MarshalAs to tell .NET that it's a pointer to an array. IIRC it was something like this (1600 = 6400/4):
void GetDeviceLongInfo(int, int, [MarshalAs(UnmanagedType.LPArray, SizeConst=1600)] int[] ar );
update
I noticed the questions on how this works, so here it is... How this signature will work: signature in C is probably (long, long, long*) which means the third argument should be a pointer to int. The underlying buffer will be filled with the GetDeviceLongInfo by means of a strncpy or something similar. Things that can go wrong is passing a buffer that's too small (that's checked running it in Debug mode in VS), using the wrong processor architecture, incorrectly passing the integer instead of a pointer (you can try casting the address of your AllocHGlobal to int and see if that works -- that does mean you will have to run on x86 though) and basically a whole lot of other things :-)
Apparently you cannot change anything to the signature. What you're basically attempting to do then is allocate a buffer, cast it to an int* and then process it. Since the approach of usr isn't working, I'd try Marshal.AllocHGlobal to create the buffer, and then pass it to the function (if needed, use unsafe code).
I have searched far and wide for an answer to my question, and all the solutions are not acceptable, not applicable, and/or confusing.
I am needing to return a string from a function implemented in C++ back to the calling code in C#.
The returned string needs to be returned as a parameter rather than a return value since I need to pass/return multiple strings for some functions. The length of the string varies, so I can't just allocate a buffer, etc.
Any help would be appreciated.
NOTE: The solution posted and mentioned by Justin and/or others is NOT a solution for my use case. As I stated in the question, I do not know the size of the string prior to making the call to the C++ code. I can't pre-allocate a StringBuffer and pass it to the C++ code.
One way is to declare the parameter as ref IntPtr. So:
static extern void DoSomething(ref IntPtr returnedString);
So you call it and get a string with:
IntPtr pstr;
DoSomething(ref pstr);
string theString = Marshal.PtrToStringAnsi(pstr);
However, it's important to remember that the returned pointer was allocated by your C++ code. If you want it to be deallocated, you'll need to call the C++ code to do it.
You might also want to look at Marshal.PtrToStringAuto, and other similar functions.
Note also that this copies the data from the pointer to the string. If you want to refer to the string in place, you'll have to play with IntPtr and the Marshal class, or delve into the wonderful world of unsafe code and pointers.
Adding to Jim Michel's answer, I would create a helper function, like
String FromCppString(IntPtr a_Pointer)
{
String result = Marshal.PtrToStringAnsi(a_Pointer);
FreeCppString(a_Pointer);
return result;
}
where FreeCppString is another function exported from C++, freeing the string properly. The original c++ function will just allocate as many strings as necessary and put them into parameters. The C# function will use FromCppString() to extract them.
Use the portable (multi-compiler multi-language) string provided by the platform for the express purpose of passing strings between components implemented in different languages -- BSTR.
In C++, you use SysAllocString or SysAllocStringLen. P/invoke already knows how to deal with these (convert to .NET string and call SysFreeString) as long as you use the right signature.
extern static void DoSomething([MarshalAs(UnmanagedType.BStr)] out String returnedString);
And then simply call it:
string theString;
DoSomething(out theString);
That's it, no special conversions or cleanup necessary, since p/invoke took care of it.
For more information, read this MSDN page on string handling in p/invoke
NOTE: I guess none of the examples in the link are exactly this case, so here's the C++ prototype
void DoSomething(__out BSTR *s);
I have an unmanaged function call that is throwing this exception when I try to pass it the path to a file name.
I've read that this is likely caused by the DLL itself but I don't think that is the case since the DLL is used in another application, so the problem is likely in my method calling the function.
The specification:
libvlc_media_new_path (libvlc_instance_t *p_instance, const char *path)
Description:
p_instance the instance
path local filesystem path
And my method:
[DllImport("libvlc", EntryPoint = "libvlc_media_new_path")]
public static extern IntPtr NewMedia(IntPtr instance,
[MarshalAs(UnmanagedType.LPStr)] string path);
I think I'm missing the convention call but what would that likely be? Or would it be something else causing this exception?
EDIT: Based on some comments I did some poking around and found... well, nothing. The struct for the instance is opaque, which means I have no idea in Laymans terms. My guess is that it means you don't need to reconstruct it in the application that is using it?
In a blind guess based on this, I replaced the return value that I had been using with the function responsible for setting the *p_instance value to a long instead of an IntPtr since when it was an IntPtr it was returning 0, and with a long I was seeing a value. Again, what an IntPtr is I don't really know. I was pretty happy to see something not 0 in the instance variable but when I ran it past that, it errored out again.
EDIT: I've expanded the question to here.
Based on the exception you're seeing and the declaration you've provided for the native function,
libvlc_media_new_path (libvlc_instance_t *p_instance, const char *path)
your p/invoke declaration is incorrect. You've mismatched the calling conventions. The default for the .NET p/invoke system is stdcall (to match the Windows API functions), but the default for C and C++ code is cdecl. You have to tell .NET explicitly that your function uses the cdecl calling convention.
So change it to look like this:
[DllImport("libvlc", EntryPoint = "libvlc_media_new_path", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr NewMedia(IntPtr instance,
[MarshalAs(UnmanagedType.LPStr)] string path);
Of course, I'm guessing that you're right about the return value being a pointer. The native function declaration you've shown is missing the return type.
As for your question about the instance parameter, and whether you are correctly using the IntPtr type: The parameter is a pointer to a libvlc_instance_t, so you have two basic ways of making that work using p/invoke. First is to declare the parameter as an IntPtr, which gets it marshalled like a raw pointer value. This is not particularly useful for cases where the pointer needs to be anything other than opaque (i.e. retrieved from one native function, stored, and then passed to another native function). Second is to declare a managed structure that mirrors the native structure, and then write the p/invoke declaration to use this structure so that the marshaller will handle things automatically. This is most useful if you actually need to interact with the values stored in the structure pointed to by the pointer.
In this case, after a Google search, it looks like you're using one of the VLC APIs. Specifically this one. That also tells us what an libvlc_instance_t is: it is an opaque structure that represents a libvlc instance. So declaring a managed structure is not an option here, because the structure is treated as opaque even by the native code. All you really need is the pointer, passed back and forth; a perfect case for the first method I talked about above. So the declaration shown above is your winner.
The only battle now is obtaining a valid pointer to a libvlc instance that you can pass to the function whenever you call it. Chances are good that will come from a prior call to a function like libvlc_new, which is documented as creating and intializing a new libvlc instance. Its return value is exactly what you need here. So unless you've already created a libvlc instance (in which case, use that pointer), you will also need to call this function and store its result.
If the documentation is correct about the required values for the libvlc_new function's parameters, you can declare it very simply:
[DllImport("libvlc", EntryPoint = "libvlc_new", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr NewCore(int argc, IntPtr argv);
And call it thus:
IntPtr pLibVlc = NewCore(0, IntPtr.Zero);
// now pLibVlc should be non-zero
And of course, I know nothing about the VLC APIs, but my general knowledge of API design tells me that you will probably need to call the libvlc_release function with that same pointer to an instance once you're finished with it.
Try without the [MarshalAs(UnmanagedType.LPStr)], usually works for me.
I'm currently working on some C#/C++ code which makes use of invoke. In the C++ side there is a std::vector full of pointers each identified by index from the C# code, for example a function declaration would look like this:
void SetName(char* name, int idx)
But now I'm thinking, since I'm working with pointers couldn't I sent to C# the pointer address itself then in code I could do something like this:
void SetName(char*name, int ptr)
{
((TypeName*)ptr)->name = name;
}
Obviously that's a quick version of what I'm getting at (and probably won't compile).
Would the pointer address be guaranteed to stay constant in C++ such that I can safely store its address in C# or would this be too unstable or dangerous for some reason?
In C#, you don't need to use a pointer here, you can just use a plain C# string.
[DllImport(...)]
extern void SetName(string name, int id);
This works because the default behavior of strings in p/invoke is to use MarshalAs(UnmanagedType.LPStr), which converts to a C-style char*. You can mark each argument in the C# declaration explicitly if it requires some other way of being marshalled, eg, [MarshalAs(UnmanagedType.LPWStr)], for an arg that uses a 2-byte per character string.
The only reason to use pointers is if you need to retain access to the data pointed to after you've called the function. Even then, you can use out parameters most of the time.
You can p/invoke basically anything without requiring pointers at all (and thus without requiring unsafe code, which requires privileged execution in some environments).
Yes, no problem. Native memory allocations never move so storing the pointer in an IntPtr on the C# side is fine. You need some kind of pinvoked function that returns this pointer, then
[DllImport("something.dll", CharSet = CharSet.Ansi)]
void SetName(IntPtr vector, string name, int index);
Which intentionally lies about this C++ function:
void SetName(std::vector<std::string>* vect, const char* name, int index) {
std::string copy = name;
(*vect)[index] = copy;
}
Note the usage of new in the C++ code, you have to copy the string. The passed name argument points to a buffer allocated by the pinvoke marshaller and is only valid for the duration of the function body. Your original code cannot work. If you intend to return pointers to vector<> elements then be very careful. A vector re-allocates its internal array when you add elements. Such a returned pointer will then become invalid and you'll corrupt the heap when you use it later. The exact same thing happens with a C# List<> but without the risk of dangling pointers.
I think it's stable till you command C++ code and perfectly aware what he does, and other developers that work on the same code know about that danger too.
So by my opinion, it's not very secure way of architecture, and I would avoid it as much as I can.
Regards.
The C# GC moves things, but the C++ heap does not move anything- a pointer to an allocated object is guaranteed to remain valid until you delete it. The best architecture for this situation is just to send the pointer to C# as an IntPtr and then take it back in C++.
It's certainly a vastly, incredibly better idea than the incredibly BAD, HORRIFIC integer cast you've got going there.
I'm porting a C++ library to C# and I've encountered some methods that have double* pointers as parameters. What's the best way to deal with this? Perhaps modify the calling code so that it's not passing pointers? I WOULD just wrap the code in an "unsafe" block and set the compiler's /unsafe flag, but I can't do that inside of the method signature.
Maybe uusing ref (or out) on parameters may be good enough, or if you need to handle an array of those use a double[].
Maybe post the method definition so that it gets clearer what you really need.
I'm assuming that you wish to use managed safe code
Depends on how the pointer is used. If it's used as an array inside your method then you'll need to pass an array to the method and therefor need to change the signature.
if it's used as a double and (re)assigned it again depends. Does the method have return type? if so using ref double might be the way to go. if the method doesn't have a return type return the value being assigned and let the caller passing to a local instead of passing by ref.
if the double* is used as a double and never assign simply pass as double.
Probably it translates to ref double or out double or double[]. Which it should be depends on the semantics of the code. C++ double* can actually mean a number of things.
It's highly unlikely that unsafe code is needed.
You could mark the function as unsafe and compile with the /unsafe flag:
private static unsafe void MyFunction(double *d)
See http://msdn.microsoft.com/en-us/library/chfa2zb8.aspx
Where you are passing pointers, you are simply changing the default pass-by-value mechanism to pass-by-reference, in which case, use the ref keyword:
public void SomeMethod(ref double val) { }
In which you need to ensure you specifiy ref when call it too:
SomeMethod(ref 12.0);
What you do will depend on how the pointer is being used. If the pointer is there so that the calling code can pass an array of doubles, then have the method accept a double[]. If the pointer is there so that the called code can modify the value of a double variable from the caller, then you have two choices:
Modify the semantics of the call in such a way that the double is a return value (this would be the way I'd suggest)
Declare the parameter as ref or out (depending on whether or not you want to guarantee that the called function will assign a value.
Don't just throw unsafe blocks around code so that you can continue to use pointers; unsafe should be used very sparingly (ideally not at all).
It depends on how the function uses the pointer. You don't really give enough info to give a solid answer, but I'll give it a shot anyway.
Normal C# code
If the code in the method is de-referencing the pointer and assigning a value, without doing any pointer arithmetic, then simply make the parameter an out parameter.
If the previous paragraph is true, and you don't already have a return value, simply modify the signature of the method to return a double.
If the code is not doing pointer arithmetic, but uses the value that already exists at the pointed location, as well as assigning it, then make the parameter a ref parameter.
If the code does no pointer arithmetic, uses the value, but doesn't assign it, then you should probably change it from a pointer to a plain double, and not make it ref or out.
If the implementation of the function is doing pointer arithmetic, then you'll need to build and pass some sort of indexable collection, such as one that implements IList or an array.
Alternatives to normal C# code
You could always opt to mark your code unsafe, too, and use pointers. That will probably be a lot more work than simple logical translations, but is more likely to maintain a similar performance profile.
You could also opt to use C++/CLI instead of C#. It is also a .Net langauge, and might be simpler (depending on your app) to integrate directly with the existing C++ code.