Hi I have create c++ function as
void MyClass::GetPRM(BSTR BString)
{
//----
}
In C# the dll interface looks like:
GetPRM(char* BString)
My question is how can I pass string as char* from c# to c++ dll?
I have tried doing
void MyClass::GetPRM(std::string BString) but no luck.
Any Suggestions
You should be able to use
[DllImport("mycppdll", EntryPoint="MyClass_GetPRM")]
extern static void GetPRM([MarshalAs(UnmanagedType.BStr)] string BString)
However, that doesn't take into account C++ name-mangling, nor your C++ method's this pointer if that method is not declared static.
On the C side, you may need a wrapper function like this:
extern "C" __declspec(dllexport) void __stdcall
MyClass_GetPRM(BSTR BString)
{
MyClass::GetPRM(BString);
}
which would require adaptation of the C# declaration to match the exported name:
[DllImport("mycppdll", EntryPoint="MyClass_GetPRM")]
extern static void GetPRM([MarshalAs(UnmanagedType.BStr)] string BString)
Related
A C# application has a static dependency on a C++ DLL. Lets say there is a function in C# application as below:
void foo(int a)
{
Console.WriteLine(a);
}
The C++ DLL has an exported function that looks like as below.
typedef void (*Func_t)(int);
extern "C" __declspec(dllexport) void bar(Func_t f)
{
f(5);
}
Can I call bar() function from the C# application and pass foo() as a parameter and expect '5' to be printed?
bar(foo);
Define a delegate
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void Func_t(int a);
Import the function
[DllImport(...)]
static extern void bar(Func_t f);
Usage
bar(foo);
I have a C++ project X with calling convention set as __stdcall (/Gz) and a C# project Y.
I have defined a class myClass in BOTH these projects.
class myClass
{
private:int mem1;
};
In the C# definition of the class, I have prefixed it with
[StructLayout(LayoutKind.Sequential)]
The C++ function is
_declspec (dllexport) void getLen(myClass* str)
{
printf("%s",sizeof(int));
}
In Y, I have defined the function as follows
[DllImport("X.dll")]
private static extern void getLen(ref myClass str);
And I am calling it like this:
getLen(ref str);
where str is an object of type myClass.
Why is this error coming up when I run this solution?
Your problem is in the printf() call: "%s" expects a pointer to a null-terminated string of characters, but you are providing a size_t.
this is my C code
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL(string a)
{
printf ("%s\n",a)
}
}
this is my C# code
class HelloWorld
{
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL(string a);
static void Main ()
{
string a = "Hello";
DisplayHelloFromDLL(a);
}
}
It built successfully but crash like this:
SO,how to use P/invoke to call my own C dll from C#?
Please help,thanx in advance.
First of all your code is C++ rather than C. Your function receives a parameter of type std::string and the use of std::string means that your code is actually C++.
Now this parameter type is the root of your problem. You cannot create a std::string in .net and instead will need to use a char* to pass the string data. The following code is what you need:
C++
__declspec(dllexport) void DisplayHelloFromDLL(char* a)
{
printf("%s\n", a);
}
C#
[DllImport("TestLib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void DisplayHelloFromDLL(string a);
static void Main ()
{
string a = "Hello";
DisplayHelloFromDLL(a);
}
The default p/invoke marshalling for a .net string is to pass a char* as an [In] parameter. There is no need for the complexity of IntPtr, StringToHGlobalAnsi, FreeHGlobal as suggested by one of the other answers. If you can let the p/invoke marshaller do the work then it is preferable to do so.
Note that you also need to make sure that your calling conventions match. Under the assumption that you have not used any special compiler options when building your C++ code, that code will default to used cdecl calling convention. You can make that match with the CallingConvention parameter to the DllImport attribute.
Please take a look at marshalling string at MSDN
In a nut shell, a C# string doesn't get marshalled as std::string but a char* by default
For one thing the return type is not matching. In C it is void and in C# int.
Change your C++ param type to char* and update your C# code as following
class HelloWorld
{
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL(IntPtr a);
static void Main ()
{
string a = "Hello";
var ptr = System.Runtime.Marshal.StringToHGlobalAnsi(a);
DisplayHelloFromDLL(ptr);
System.Runtime.Marshal.FreeHGlobal(ptr);
}
}
This one is basic, how do I call the function SubscribeNewsFeed in the following from a C# DllImport?
class LogAppender : public L_Append
{
public:
LogAppender()
: outfile("TestLog.txt", std::ios::trunc | std::ios::out)
, feedSubscribed(false)
{
outfile.setf(0, std::ios::floatfield);
outfile.precision(4);
}
void SubscribeNewsFeed()
{
someOtherCalls();
}
};
I'm unable to figure out how to include the class name when using the DllImport in my C# program here:
class Program
{
[DllImport("LogAppender.dll")]
public static extern void SubscribeNewsFeed();
static void Main(string[] args)
{
SubscribeNewsFeed();
}
}
PInvoke cannot be used to call directly into a C++ function in this way. Instead you need to define an extern "C" function which calls the PInvoke function and PInvoke into that function. Additionally you cannot PInvoke into a class instance method.
C / C++ Code
extern "C" void SubscribeNewsFeedHelper() {
LogAppender appender;
appender.SubscribeNewsFeed();
}
C#
[DllImport("LogAppender.dll")]
public static extern void SubscribeNewsFeedHelper();
P/Invoke doesn't work that way. It only can import C functions. So there are different types of interop between the managed (C#) and native (C++) world. Interop via COM would be a solution - providing a C interface another.
I have a C# application that calls functions in a DLL written in C++. The calls work fine and the code is executed using this method in the C#:
[DllImport("myDLL.dll")]
public static extern void Function();
static void Main()
{
Function();
}
Now this works, I need the executing C++ code to send back the text to the C# where it can be displayed in a panel.
The text is "stage one..." executes code...then "stage two" etc, showing the processes running. Just basic stuff. I'm not sure how to approach this as I'm not a C++ guy. My main skills are .NET.
Cheers
Try using callbacks in C++ and sign them in C#
C++ part
typedef void (CALLBACK *pfNotifyMessage)(LPTSTR);
extern "C" AFX_API_EXPORT void SetNotifyMessage(pfNotifyMessageType pfNotify);
extern "C" AFX_API_EXPORT void Function();
In C++ Function call make call of pfNotifyMessage
C# part
public delegate void NotifyMessage(string message);
[DllImport("myDLL.dll")]
public static extern void SetNotifyMessage(NotifyMessage notify);
[DllImport("myDLL.dll")]
public static extern void Function();
in ะก# assign delegate with function