asmyatt
asked on
Pass variables from Unmanaged C++ dll to C#
Hi Experts,
I have written a dll that queries a database and does some other unimportant stuff. I pass the dll 2 strings and the DLL will return a vector. It will work fine if the calling program is a C++ program. However, I am going to need this to be able to be called from a C# program. I understand how to call the DLL; the thing I'm not sure about is how to handle the vector of strings that the dll will return. How do I handle the vector in C#? I don't mind changing the data structure that the dll returns if it will make things easier. Any help is appreciated.
Thanks
I have written a dll that queries a database and does some other unimportant stuff. I pass the dll 2 strings and the DLL will return a vector. It will work fine if the calling program is a C++ program. However, I am going to need this to be able to be called from a C# program. I understand how to call the DLL; the thing I'm not sure about is how to handle the vector of strings that the dll will return. How do I handle the vector in C#? I don't mind changing the data structure that the dll returns if it will make things easier. Any help is appreciated.
Thanks
Please show Dll function prototype and describe shortly function parameters. If you have working C++ client code which calls this function, post it also.
ASKER
Through some research I have concluded that what I want to do may not be possible. What I would like to happen is have my function prototyped in the unmanaged C++ dll like so:
struct ResultSet
{
string name;
string value;
}
DBDLL_API list<ResultSet> ExecuteQuery (string inputQuery, string tableName);
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
then in the C# program that will call this dll I would like to do something like this:
struct ResultSet
{
string name;
string value;
}
[DllImport("DBDLL.dll",Cha rSet = CharSet.Ansi)]
static extern list<ResultSet> ExecuteQuery (string inputQuery, string tableName);
list<ResultSet> returnSet = ExecuteQuery "A AND B OR C", "Employee");
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----
When I run the program I get this exception: Cannot marshal 'return value': Generic types cannot be marshaled
I figure there must be some way to return an object, list, or non-primitive data type from the dll, but I cannot figure it out.
Thanks
struct ResultSet
{
string name;
string value;
}
DBDLL_API list<ResultSet> ExecuteQuery (string inputQuery, string tableName);
--------------------------
then in the C# program that will call this dll I would like to do something like this:
struct ResultSet
{
string name;
string value;
}
[DllImport("DBDLL.dll",Cha
static extern list<ResultSet> ExecuteQuery (string inputQuery, string tableName);
list<ResultSet> returnSet = ExecuteQuery "A AND B OR C", "Employee");
--------------------------
When I run the program I get this exception: Cannot marshal 'return value': Generic types cannot be marshaled
I figure there must be some way to return an object, list, or non-primitive data type from the dll, but I cannot figure it out.
Thanks
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I figured it would require something like that. I know nothing about a C++/CLI wrapper so off to google I go. If you have any links that are good, or can provide some good examples I would appreciate it.
Thanks
Thanks
Advantage of C++/CLI is that you can use unmanaged code in it directly. You can create C++/CLI class library and add method to it, which can be handled directly by C# client. For example, you can create method which looks in C# like:
ArrayList GetData(); // ArrayList contains String members
In C++/CLI it can look like this:
#include <list>
...
piblic: ArrayList^ GetData()
{
ArrayList^ result = gcnew ArrayList();
// enumerate std::list here and add every string to result
return result;
}
Ask specific questions in Managed C++ area.
If you need to work with unmanaged code, C++/CLI it the best way, it is more flexible than PInvoke.
ArrayList GetData(); // ArrayList contains String members
In C++/CLI it can look like this:
#include <list>
...
piblic: ArrayList^ GetData()
{
ArrayList^ result = gcnew ArrayList();
// enumerate std::list here and add every string to result
return result;
}
Ask specific questions in Managed C++ area.
If you need to work with unmanaged code, C++/CLI it the best way, it is more flexible than PInvoke.