I have a function in C++, _GetFileList, that I am trying to get to return a list/array of strings to C# code. I am not married to wstring * or any other type, this is just how the example I had found did it, but I am trying to get it to return a list/array and not just a single string. How can I marshal this to have multiple strings on the C# side?
C++ code:
extern "C" __declspec(dllexport) wstring * __cdecl _GetFileList(int &size){
std::list<wstring> myList;
//Code that populates the list correctly
size = myList.size();
wstring * arr = new wstring[size];
for( int i=0;i<size;i++){
arr[i] = myList.front();
myList.pop_front();
}
return arr;
}
I call that from C# like this:
[DllImport(#"LinuxDirectory.Interface.dll")]
private static extern IntPtr _GetFileList(ref int size);
public bool GetFileList() {
int size = 0;
IntPtr ptr = _GetFileList( ref size );
//WHAT DO I DO HERE TO GET THE LIST OF STRINGS INTO SOMETHING I CAN READ?
}
I've tried to use Marshal.PtrToStringUni, Marshal.PtrToStringAnsi, and the structure one as well but couldn't seem to get the syntax correct.
You don't. P/Invoke can only deal with function signatures that are C-compatible, meaning pointers have to be to plain-old-data, not full C++ classes.
If you can rewrite the C++ code, change it to call SysAllocString and return a BSTR, which the OS-provided string type intended for data exchange between components written in different languages. P/invoke already has all the right magic for receiving a BSTR, just use the C# string type in the p/invoke declaration.
If you can't change the C++ signature, you'll have to wrap it. Either use C++/CLI, which can deal with C++ classes as well as .NET, or use standard C++ and create and return a BSTR, copying data from the std::wstring.
For multiple strings, you can use the OS-provided type for array (SAFEARRAY) which is able to carry BSTR inside and again is language independent. Or it may be easier to just join and split using an appropriate (not appearing naturally in the data) separator character.
There's some really great information here: https://msdn.microsoft.com/en-us/magazine/mt795188.aspx
Running .NET Framework (the Microsoft implementation, on Windows), you can use the helper classes:
#include <windows.h>
#include <atlbase.h>
#include <atlsafe.h>
#include <string>
extern "C" __declspec(dllexport) LPSAFEARRAY GetFileList()
{
std::vector<std::wstring> myList;
//Code that populates the list correctly
size = myList.size();
CComSafeArray<BSTR> sa(size);
int i=0;
for( auto& item : myList ) {
CComBSTR bstr(item.size(), &item[0]);
sa.SetAt(i++, bstr.Detach()); // transfer ownership to array
}
return sa.Detach(); // transfer ownership to caller
}
On the C# side, p/invoke handles it all:
[DllImport("NativeDll.dll"),
return:MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
public static extern string[] GetFileList();
Your question suggests you might be on Linux. Unfortunately, the documentation I found seems to say that Mono's p/invoke doesn't know what to do with variable-sized arrays at all. So you're stuck doing everything by hand, including deallocation (the code in your question leaks new wstring[size] -- C# has absolutely no clue how to call a C++ delete[] operator). Have a look at Mono.Unix.UnixMarshal.PtrToStringArray.
Related
I have to find the way to build the array of structs on C++ Win32 side. I don't have the initial number of items. It should be very fast to resize that array.
When the list is build, I need to return it back to .NET. So That array(list) should be converted to the transport which easily can be read on .NET side or the initial list can be used "as is" just passing the pointer.
Thanks in advance for giving me a hint!
A very common way of implementing "dynamic arrays" in C++ is to use STL's std::vector. In your case, you can define a vector<SomeData>. std::vector can change its size dynamically (i.e. at run-time), as per your request: you can use its push_back or emplace_back methods for that purpose, adding new items to the vector.
However, C# doesn't "understand" std::vector.
To marshal its content to C#, you could use a SAFEARRAY, which the CLR understands very well. The good thing about SAFEARRAY is that it stores also the array size, besides the array content: it's a self-contained data structure.
So, you can create a SAFEARRAY of proper size, fill it with the content dynamically created in the vector, and pass that SAFEARRAY to C#.
Note that you could also build a SAFEARRAY directly, without passing for std::vector. But STL's vector has a more powerful programming interface; so if you want to do several additions of items via push_back or emplace_back at run-time, building the std::vector first, and then "marshalling" it into a SAFEARRAY, could be a better option. Anyway, that depends on your particular needs and context.
As an alternative, you could use C++/CLI as a bridging layer between the C++ side and the C# side. In this case you could use gcnew to create a .NET "managed" array.
And, as another option, you could export a couple of functions from your native C++ DLL with a C interface:
a function to get the count of items in the array
another function to get the actual array data in an output caller-allocated buffer (the size of which is returned by the previous function)
In C#, the output buffer pointer is passed using an IntPtr output parameter.
You can then use Marshal.PtrToStructure to marshal a single data item, and you can increase the pointer using Marshal.SizeOf, to make it point to the next item in the array.
Something like this:
// In C++:
struct SomeData
{
/* your data fields */
};
// Export these two functions from your native DLL:
extern "C" int GetSomeDataCount( /* some params */ );
extern "C" void GetSomeData( SomeData* ptr, /* some other params */ );
// In C#:
public struct SomeData
{
// Map C++ data structure fields to C#
}
static extern int GetSomeDataCount( /* some params */ );
static extern void GetSomeData( [Out] out IntPtr ptr, /* some other params */ );
SomeData[] GetSomeData( /* some params */ )
{
// Allocate an array of proper size
SomeData[] dataArray = new SomeData[ GetSomeDataCount( /* some params */ ) ];
// Fill the array with content from GetSomeData
IntPtr dataPtr;
GetSomeData( out dataPtr, /* some other params */ );
for (int i = 0; i < dataArray.Length; i++)
{
dataArray[i] = Marshal.PtrToStructure(dataPtr, typeof(SomeData));
dataPtr += Marshal.SizeOf(typeof(SomeData));
}
return dataArray;
}
Generally if your C++ dll compiled with CLI support you can simply use managed containers. If you don't want your dll to be compiled with CLI option, then you may write small C++/CLI wrapper dll which will call methods from native C++ dll and store objects in the managed container.
Another possible solution is to change interface of the C++ lib to return objects by indexes, support insertion and/or removal.
std::vector<CFoo> vec;
void init() {
//read data to vec
}
CFoo getIthElement(int i) {
return vec[i];
}
int getElementCount() {
return vec.size();
}
So you will use getIthElement and getElementCount functions on the C# side.
I am new to C# but have worked extensively with C++. I have a C++ function that needs to be called from C#. After reading some answers from SO and some googling, I conclude that I need to make a pure C interface to the function. I have done this, but am still confused about how to call it from C#.
The function in C++ looks like this:
int processImages(
std::string& inputFilePath, // An input file
const std::vector<std::string>& inputListOfDirs, // Input list of dirs
std::vector<InternalStruct>& vecInternalStruct, // Input/Output struct
std::vector<std::vector< int > >& OutputIntsForEachFile,
std::vector< std::vector<SmallStruct> >& vecVecSmallStruct, // Output
int verboseLevel
);
The same function, converted in C, looks like this:
int processImagesC(
char* p_inputFilePath, // An input file
char** p_inputListOfDirs, // Input list of dirs
size_t* p_numInputDirs, // Indicating number of elements
InternalStruct* p_vecInternalStruct, // Input/Output struct
size_t* p_numInternalStructs,
int** p_OutputIntsForEachFile, // a 2d array each row ending with -1
size_t* p_numOutputIntsForEachFile //one number indicating its number of rows
SmallStruct** p_vecVecSmallStruct, // Output
size_t* p_numInVecSmallStruct,
int verboseLevel
);
This is based on this advice.
Now I need to call this from C#, which is where the confusion is. I have tried my best to convert the structures.
The C# code looks like this:
[DllImport(
#"C:\path\to\cppdll.dll", CallingConvention=CallingConvention.Cdecl,
EntryPoint="processImagesC", SetLastError=true)]
[return: MarshalAs(UnmanagedType.I4)]
unsafe public static extern int processImagesC(
String inputFilePath,
String[] inputListOfDirs,
ref uint numInputListOfDirs,
// Should I use ref InternalStruct * vecInternalStruct?
ref InternalStruct[] vecInternalStruct,
ref uint numInternalStruct,
// Or ref int[] or ref int[][] or int[][]?
ref int[][] OutputIntsForEachFile,
ref uint numOutputIntsForEachFile,
// again, ref ..[], [][], or ref [][]?
ref SmallStruct[][] vecVecSmallStruct,
int verboseLevel
);
There are memory allocations for all the output variables (pointers) done within the C/C++ code. This likely means we need to declare the code as unsafe, correct?
How do we handle memory deallocation? Should I write another API (function) that does the deallocation of objects/arrays allocated by C/C++?
The C++ code needs to be standard compliant and platform independent, so I cannot insert any windows-specific things in it.
I hope someone could make sense of this and provide an answer or at least point me in the right direction.
Since there seems to be some interest in using It Just Works (IJW) with C++/CLI, I'll post some info about that, further google searches and research will need to be done to figure it all. C++/CLI can be enabled with a single compiler flag (/CLI, enabled through Property Page->General->Common Language Runtime Support). C++/cli is NOT c++, but rather just another managed language. C++/CLI classes can be compiled into dll's and called directly from other .NET projects (C#, VB.NET, ect). However, unlike the other .NET languages it can directly interact with C++ code.
This is an ok start to learning C++/CLI. The big thing to learn is the decorations that tell you the class is managed (.NET class) and not Vanila C++. The "ref" keyword decalres the definition as a .NET definition:
public ref class Foo{ public: void bar();};//Managed class, visible to C#
public ref struct Foo{};//Managed struct, visible to C#
All reference classes are referred to with Handles rather than pointers or references. A handle is denoted by the ^ operator. To make a new handle, you use gcnew, and to access functions/members of the handle, use the -> operator.
//in main
Foo^ a = gcnew Foo();
a->bar();
You often have to move structures common from C# to native types and back again. (such as managed Array^ or String^ to void* or std::string). This process is called Marshaling. This handy table is pretty useful for figuring that out.
A common task is to create a wrapper for a native class, done like this:
//Foo.h
#include <string>
namespace nativeFoo
{
class Foo
{
private:
std::string fooHeader;
public:
Foo() {fooHeader = "asdf";}
std::string Bar(std::string& b) {return fooHeader+b;}
};
}
//ManagedFoo.h
#include "foo.h"
namespace managedFoo
{
public ref class Foo
{
private:
nativeFoo::Foo* _ptr;
public:
Foo(){_ptr = new nativeFoo::Foo();}
~Foo(){!Foo();}
!Foo(){if (_ptr){delete ptr;ptr = NULL;}}
String^ bar(String^ b)
{
return marshal_as<String^>(_ptr->bar(marshal_as<std::string>(b)));
}
};
}
Warning: I am totally missing a bunch of #include and #using statements, this is just to give a general gist of how to use this.
Begin from this:
How to pass structure as pointer in C dll from C#
And something about marshalling in this:
Deep copying an array c# without serialization
Note that Marshal.Copy also overloads for arrays use. With marshalling you can get rid of ref excepting that you do want to. Just write C/C++ in their way.
And following is a little bit complicated:
Physical disk size not correct (IoCtlDiskGetDriveGeometry)
The 2 ways I've often seen this handled is to either have a 'FreeResource' style API, or specify in the function the size of output buffers.
Method 1
C++
void GetName(char ** _str)
{
if (!_str)
return; // error
*_str = new char[20];
strcpy(*str, "my name");
}
void FreeString(char * _str)
{
delete str;
}
Client (any language)
char * name;
GetName(&name);
...
FreeString(name);
Method 2
C++
void GetName(char * _str, size_t _len)
{
if (_len < 20)
return; // error
strcpy(str, "my name");
}
Client (any language)
char * name = new char[20];
GetName(name, 20);
...
If you are willing to use third party tool, there is a tool named C#/.NET PInvoke Interop SDK may be helpful to you. But you can do it yourself as well. For simple classes with a few methods, you can write your own code in managed C# code.
The basic idea of instantiating a C++ object from .NET world is to allocate exact size of the C++ object from .NET, then call the constructor which is exported from the C++ DLL to initialize the object, then you will be able to call any of the functions to access that C++ object, if any of the method involves other C++ classes, you will need to wrap them in a C# class as well, for methods with primitive types, you can simply P/Invoke them. If you have only a few methods to call, it would be simple, manual coding won't take long. When you are done with the C++ object, you call the destructor method of the C++ object, which is a export function as well. if it does not have one, then you just need to free your memory from .NET.
Here is an example.
public class SampleClass : IDisposable
{
[DllImport("YourDll.dll", EntryPoint="ConstructorOfYourClass", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void SampleClassConstructor(IntPtr thisObject);
[DllImport("YourDll.dll", EntryPoint="DoSomething", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void DoSomething(IntPtr thisObject);
[DllImport("YourDll.dll", EntryPoint="DoSomethingElse", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void DoSomething(IntPtr thisObject, int x);
IntPtr ptr;
public SampleClass(int sizeOfYourCppClass)
{
this.ptr = Marshal.AllocHGlobal(sizeOfYourCppClass);
SampleClassConstructor(this.ptr);
}
public void DoSomething()
{
DoSomething(this.ptr);
}
public void DoSomethingElse(int x)
{
DoSomethingElse(this.ptr, x);
}
public void Dispose()
{
Marshal.FreeHGlobal(this.ptr);
}
}
For the detail, please see the below link,
C#/.NET PInvoke Interop SDK
The tool, xInterop NGen++ 2.0 has been released. Please check it out if you are interested in creating C# wrapper for native C++ DLL.
(I am the author of the SDK tool)
I have written a C# application that injects a DLL into a third-party executable (which happens to have been built using the Qt framework). This DLL uses EasyHook to intercept calls to a number of specific functions. When my injected code is called, I then try to inspect some of the objects that are parameters to these functions.
For example, I have intercepted a call made to parse some XML:
virtual bool __thiscall QXmlSimpleReader::parse(class QXmlInputSource const &)
In my C# code, I have a PInvoke signature to match this:
static extern bool XmlParse(IntPtr Reader, IntPtr Source)
I would like to call the "data()" function which is a member of the "Source" class. That is, the QXmlSimpleReader parses the raw XML from the QXmlInputSource, but before it does so, I am trying to inspect the raw XML via this "data()" function.
On the advice of one of the experts here, I have tried to use C++/CLI to access the object natively (see Calling methods in third-party DLLs ). I have constructed a wrapper object in C++ that accepts the IntPtr from the C# code:
Header:
public ref class QXmlInputSource
{
public:
// Constructor must be called with C# IntPtr
QXmlInputSource(IntPtr Ptr);
bool LoadQt(void);
bool UnloadQt(void);
String^ Data();
private:
// Pointer to the native Qt object
void * Native;
HINSTANCE DllHandle;
// SIGNATURE: virtual QString QXmlInputSource::data() const
typedef void * (__thiscall *QXmlInputSource_Data)(void *);
QXmlInputSource_Data fpData;
};
CPP file:
QXmlInputSource::QXmlInputSource(IntPtr Ptr)
{
LoadQt();
Native = Ptr.ToPointer();
}
bool QXmlInputSource::LoadQt(void)
{
FARPROC Addr;
/* get handle to dll */
std::wstring LibName = QtPath + QtXml;
DllHandle = LoadLibrary(LibName.c_str());
/* get pointer to the function in the dll*/
Addr = GetProcAddress(HMODULE (DllHandle), "?data#QXmlInputSource##UBE?AVQString##XZ");
fpData = QXmlInputSource_Data(Addr);
return true;
}
bool QXmlInputSource::UnloadQt()
{
/* Release the Dll */
FreeLibrary(DllHandle);
return true;
}
String^ QXmlInputSource::Data()
{
void* Ptr = fpData(Native);
return "EPIC FAIL";
}
The Qt-based application crashes when I try to call the fpData() function pointer. Help :P
Some additional information which may or may not help:
I have successfully called functions on "simpler" objects, such as QString.count() and QString.data() using the same methodology. (QString seems to be just a lightweight wrapper for a standard unicode string).
In the QtXml4.dll file that contains the XML functions I am interested in, there are actually TWO parse() methods; one where the Source is a const &, and in the other, Source is a const *. I have no idea if I should be using one or the other. I don't think my signatures will change in any event.
While I was trying to play around, I tried dereferencing the IntPtr in the C# code and passing it to C++:
IntPtr DerefSrc = (IntPtr)Marshal.PtrToStructure(Source, typeof(IntPtr));
If I print out the values of these two IntPtrs, Source has a value of around 3.5Mb, while the DerefSrc has a value of 1.6Gb - which roughly matches the address of the QtXml4.dll in memory. My guess is that the 3.5Mb is a relative offset, while the DerefSrc is clearly an absolute reference. Is it worth a shot converting the DerefSrc to a relative address and passing that to C++ instead ... ?
I see several problems:
1.: You don't check the return value of LoadLibrary and GetProcAddress. Is QXmlInputSource::data even a DLL-exported method? If not then GetProcAddress will obviously fail.
2.: How do you instantiate the QXmlInputSource class? I ask because it seems you are trying to do it in the C# code, which is hard to do right (you need to know the size required for the class, allocate a properly aligned chunk of memory of that size, and call the constructor on it).
3.: The way you're invoking the function pointer is wrong. You need to declare a method pointer of the appropriate type:
FARPROC fp = ::GetProcAddress(...);
typedef QString (QXmlInputSource::*DataMethod)();
DataMethod mpData = reinterpret_cast<DataMethod>(fp);
QXmlInputSource source;
QString data = (source.*mpData)();
4.: Looking at the documentation for QXmlInputSource::data, I see that it returns a QString, which is woefully different from a pointer (as you're currently treating it). To convert it to a System.String, you need code like this:
QString s1 = (QChar*)L"example string";
String^ s2 = gcnew String((wchar_t*)s1.data()); // calls the String::String(wchar_t*) constructor overload
I am writing C# code that call a C library and something it is not quite clear in my mind.
The C function has this signature:
double* DoSomeStuff(double* input,int numberOfElements);
I have mapped the function as:
[System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint="DoSomeStuff")]
public static extern System.IntPtr DoSomeStuff(ref double input, int numberOfElements) ;
The input value is an array, so the C function will expect a contiguous memory layout. I am more familiar with C++ than C#. In C++ I'd used a std::vector to store the data and then I would use the data() method to get the pointer and exchange the information with C code. std::vector guarantees a contiguous layout memory.
Which data structure can I used in C#? Is there anything like std::vector in C#?
I have faced before the same problem for a string (In C++ std::string is just a std::vector with some make up). And I have solve the problem using:
System.IntPtr stringExample = Marshal.StringToHGlobalAnsi("StringExample");
The static function does the job for me. There is anything like this function for other types?
I have asked already too many questions, I think the most important one is: what is the best practise to solve this kind of problem?
Thanks
1)
Define the input as IntPtr:
[System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint="DoSomeStuff")]
public static extern System.IntPtr DoSomeStuff(IntPtr input, int numberOfElements) ;
2)
Create an array in a fixed block, then create an IntPtr from the Pointer and then pass it to DoSomeStuff.
double[] input = new double[20];
IntPtr result = IntPtr.Zero;
fixed(double* d = &input[0])
{
result = DoSomeStuff(new InptPtr(d), 20);
}
...
Reason for the fixed block is so that GC does not move the array while unmanaged code is populating it.
To make your example work you should define the siganture of the extern function as follows:
[System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint="DoSomeStuff")]
public static extern System.IntPtr DoSomeStuff([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)], int numberOfElements);
The second (named) parameter of MarshalAs attaribute tells to the marshaller where the size of the array stored.
Regarding the second question, C# has List<Type> class that behaves similary to std:vector<Type>. However, I don't think you can directly provide it to the marshaller. What you can do is to use ToArray() methor of the List class, to get an array.
I'm calling functions from C++ that returns a pointer to an array of struct and I'm having problems since I'm new to this operation/implementation.
My C++ codes:
// My C++ Structs
typedef struct _MainData {
double dCount;
DataS1 *DS1;
int iCount1;
DataS2 *DS2;
int iCount2;
}MainData;
typedef struct _DataS1 {
unsigned int uiCount1;
unsigned int uiCount2;
int iCount;
void *pA;
void *pB;
} DataS1;
typedef struct _DataS2 {
unsigned int uiCount1;
unsigned int uiCount2;
unsigned int uiCount3;
unsigned int uiCount4;
double dCount;
int iCount1;
char strLbl[64];
} DataS2;
// My C++ Function
MainData* GetData(const int ID)
{
MainData* mData;
int iLength = Get_Count();
mData = new MainData[iLength];
for(int x = 0;x < VarCounter; x++)
{
// Codes here assign data to mData[x]
}
return mData;
}
Question:
How can I call the C++ function GetData to C#?
My current codes in C# are:
[DllImport(".\\sdata.dll")]
[return: MarshalAs(UnmanagedType.LPArray)]
private static unsafe extern MainData[] GetData(int ID);
// The struct MainData in my C# side is already "Marshalled"...
//My function call is here:
MainData[] SmpMapData = GetData(ID);
When I compiled it, there's an exception:
"Cannot marshal 'return value': Invalid managed/unmanaged type combination."
Sorry for the poor coding... Please help...
First, you need to remember that MarshalAs (explicit or implicit) for the return value essentially means "copy native structures content into managed structures".
Second, since the CLR marshaler only copies the data, if you do not free the memory you're allocated in the C++ function, you've got a memory leak to manage.
Third, this error is mainly due to the fact that the CLR marshaler has no way of knowing the length of the array returned by the native code, since you're basically returning a memory pointer and no length.
If you want to keep these memory structures as-is, I strongly suggest you to look into C++/CLI. You'll be able to wrap those complex types into mixed native/managed classes that will avoid you to copy the data around. This will help you keep the data marshaling to the bare minimum between native and managed code.
If you still want to use C# and no C++/CLI, you'll have to write a somehow smarter piece of code to unmarshal the data returned by the native code into managed data. You can look into Custom Marshaling for that.
I don't see how the .NET runtime could possibly know how many MainData are allocated in GetData(...).
Refactor your C++ code to consume an array to populate or return single MainDatas.