Calling C++ function with LPStr return value from C#
up vote
-1
down vote
favorite
I have a C++ dll in 64-Bit, which contains a function that returns an LPStr. I would like to call this function in C#. The function declaration looks like this:
__declspec(dllexport) LPSTR __stdcall function(int16_t error_code);
In my C# code I have tried the following:
[DllImport(@"<PathToInterface.dll>", EntryPoint = "function")]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string function(Int16 error_code);
And then in the program:
string ErrorMessage = "";
ErrorMessage = function(-10210);
I know that the function itself is good, as I can call it from another program (written in LabVIEW FWIW). But when I execute the C# Program, it just exits with error code 0x80000003, I can't even try, catch the exeption.
How do I call this function properly?
As a side node: I do have other functions in this dll, that use LPStr as parameters, which I can call without a problem. It is only two functions that return LPStr that make problems
c# c++ dll lpstr
add a comment |
up vote
-1
down vote
favorite
I have a C++ dll in 64-Bit, which contains a function that returns an LPStr. I would like to call this function in C#. The function declaration looks like this:
__declspec(dllexport) LPSTR __stdcall function(int16_t error_code);
In my C# code I have tried the following:
[DllImport(@"<PathToInterface.dll>", EntryPoint = "function")]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string function(Int16 error_code);
And then in the program:
string ErrorMessage = "";
ErrorMessage = function(-10210);
I know that the function itself is good, as I can call it from another program (written in LabVIEW FWIW). But when I execute the C# Program, it just exits with error code 0x80000003, I can't even try, catch the exeption.
How do I call this function properly?
As a side node: I do have other functions in this dll, that use LPStr as parameters, which I can call without a problem. It is only two functions that return LPStr that make problems
c# c++ dll lpstr
Howfunctionis implemented? Most important is how you are allocating return value
– Selvin
Nov 7 at 21:47
I read that you will need to defined export with an extern "C" block like this: extern "C" __declspec(dllexport) int captureCamera(int& captureId) { ... }
– Brian Clink
Nov 7 at 22:00
0x80000003 is E_INVALIDARG. Now, i obviously don't know which piece of the native code executed by that DLL function causes the error; but start with verifying whether the function you call actually "understands" the value-10210(i.e., does a corresponding error message/text string exist for this particular value?)
– elgonzo
Nov 7 at 22:01
add a comment |
up vote
-1
down vote
favorite
up vote
-1
down vote
favorite
I have a C++ dll in 64-Bit, which contains a function that returns an LPStr. I would like to call this function in C#. The function declaration looks like this:
__declspec(dllexport) LPSTR __stdcall function(int16_t error_code);
In my C# code I have tried the following:
[DllImport(@"<PathToInterface.dll>", EntryPoint = "function")]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string function(Int16 error_code);
And then in the program:
string ErrorMessage = "";
ErrorMessage = function(-10210);
I know that the function itself is good, as I can call it from another program (written in LabVIEW FWIW). But when I execute the C# Program, it just exits with error code 0x80000003, I can't even try, catch the exeption.
How do I call this function properly?
As a side node: I do have other functions in this dll, that use LPStr as parameters, which I can call without a problem. It is only two functions that return LPStr that make problems
c# c++ dll lpstr
I have a C++ dll in 64-Bit, which contains a function that returns an LPStr. I would like to call this function in C#. The function declaration looks like this:
__declspec(dllexport) LPSTR __stdcall function(int16_t error_code);
In my C# code I have tried the following:
[DllImport(@"<PathToInterface.dll>", EntryPoint = "function")]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string function(Int16 error_code);
And then in the program:
string ErrorMessage = "";
ErrorMessage = function(-10210);
I know that the function itself is good, as I can call it from another program (written in LabVIEW FWIW). But when I execute the C# Program, it just exits with error code 0x80000003, I can't even try, catch the exeption.
How do I call this function properly?
As a side node: I do have other functions in this dll, that use LPStr as parameters, which I can call without a problem. It is only two functions that return LPStr that make problems
c# c++ dll lpstr
c# c++ dll lpstr
asked Nov 7 at 21:37
Pete
209
209
Howfunctionis implemented? Most important is how you are allocating return value
– Selvin
Nov 7 at 21:47
I read that you will need to defined export with an extern "C" block like this: extern "C" __declspec(dllexport) int captureCamera(int& captureId) { ... }
– Brian Clink
Nov 7 at 22:00
0x80000003 is E_INVALIDARG. Now, i obviously don't know which piece of the native code executed by that DLL function causes the error; but start with verifying whether the function you call actually "understands" the value-10210(i.e., does a corresponding error message/text string exist for this particular value?)
– elgonzo
Nov 7 at 22:01
add a comment |
Howfunctionis implemented? Most important is how you are allocating return value
– Selvin
Nov 7 at 21:47
I read that you will need to defined export with an extern "C" block like this: extern "C" __declspec(dllexport) int captureCamera(int& captureId) { ... }
– Brian Clink
Nov 7 at 22:00
0x80000003 is E_INVALIDARG. Now, i obviously don't know which piece of the native code executed by that DLL function causes the error; but start with verifying whether the function you call actually "understands" the value-10210(i.e., does a corresponding error message/text string exist for this particular value?)
– elgonzo
Nov 7 at 22:01
How
function is implemented? Most important is how you are allocating return value– Selvin
Nov 7 at 21:47
How
function is implemented? Most important is how you are allocating return value– Selvin
Nov 7 at 21:47
I read that you will need to defined export with an extern "C" block like this: extern "C" __declspec(dllexport) int captureCamera(int& captureId) { ... }
– Brian Clink
Nov 7 at 22:00
I read that you will need to defined export with an extern "C" block like this: extern "C" __declspec(dllexport) int captureCamera(int& captureId) { ... }
– Brian Clink
Nov 7 at 22:00
0x80000003 is E_INVALIDARG. Now, i obviously don't know which piece of the native code executed by that DLL function causes the error; but start with verifying whether the function you call actually "understands" the value
-10210 (i.e., does a corresponding error message/text string exist for this particular value?)– elgonzo
Nov 7 at 22:01
0x80000003 is E_INVALIDARG. Now, i obviously don't know which piece of the native code executed by that DLL function causes the error; but start with verifying whether the function you call actually "understands" the value
-10210 (i.e., does a corresponding error message/text string exist for this particular value?)– elgonzo
Nov 7 at 22:01
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
How do I call this function properly?
As interop? you can't ... it is also error prone in plain C++
you should rather do it like
extern "C" __declspec(dllexport) int __stdcall function(int16_t error_code,
LPSTR buffer, size_t size)
{
LPCSTR format = "error: %i";
size_t req = _scprintf(format, error_code); // check for require size
if (req > size) //buffer size is too small
{
return req; //return required size
}
sprintf_s(buffer, size, format, error_code); //fill buffer
return 0;
}
And usage
class Program
{
static void Main(string args)
{
short error_code = -10210;
var ret = function(error_code, null, 0); // check for required size of the buffer
var sb = new StringBuilder(ret); // create large enough buffer
ret = function(error_code, sb, (uint)sb.Capacity + 1); //call again
var error_desc = sb.ToString(); //get results
Console.WriteLine(error_desc);
Console.ReadKey();
}
[DllImport("TestDll.dll", EntryPoint = "function", CharSet = CharSet.Ansi)]
public static extern int function(short error_code, StringBuilder sb, int size);
}
usage in C++
typedef int (__stdcall *function)(int16_t error_code, LPSTR buffer, size_t size);
int main()
{
auto handle = LoadLibrary(L"TestDll.dll");
auto proc = (function)GetProcAddress(handle, "_function@12");
// of course it can be done via linking
int16_t error_code = 333;
const int ret = proc(error_code, NULL, 0); // check for size
CHAR* buffer = new CHAR[ret + 1];
//CHAR buffer[200]; //eventually allocate on stack
//but size have to be constant value and may be too small
proc(error_code, buffer, ret+1); // call again
MessageBoxA(0, buffer, "Return", 0); //show result
delete buffer; //free buffer!
FreeLibrary(handle);
return 0;
}
Thanks for your answer. It is a shame, that this cannot be handled differently as not everyone has that much control over their Dlls. (It could be a third party dll, in which case that would be it). We followed your instructions and managed to make it work that way.
– Pete
Nov 12 at 18:45
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
How do I call this function properly?
As interop? you can't ... it is also error prone in plain C++
you should rather do it like
extern "C" __declspec(dllexport) int __stdcall function(int16_t error_code,
LPSTR buffer, size_t size)
{
LPCSTR format = "error: %i";
size_t req = _scprintf(format, error_code); // check for require size
if (req > size) //buffer size is too small
{
return req; //return required size
}
sprintf_s(buffer, size, format, error_code); //fill buffer
return 0;
}
And usage
class Program
{
static void Main(string args)
{
short error_code = -10210;
var ret = function(error_code, null, 0); // check for required size of the buffer
var sb = new StringBuilder(ret); // create large enough buffer
ret = function(error_code, sb, (uint)sb.Capacity + 1); //call again
var error_desc = sb.ToString(); //get results
Console.WriteLine(error_desc);
Console.ReadKey();
}
[DllImport("TestDll.dll", EntryPoint = "function", CharSet = CharSet.Ansi)]
public static extern int function(short error_code, StringBuilder sb, int size);
}
usage in C++
typedef int (__stdcall *function)(int16_t error_code, LPSTR buffer, size_t size);
int main()
{
auto handle = LoadLibrary(L"TestDll.dll");
auto proc = (function)GetProcAddress(handle, "_function@12");
// of course it can be done via linking
int16_t error_code = 333;
const int ret = proc(error_code, NULL, 0); // check for size
CHAR* buffer = new CHAR[ret + 1];
//CHAR buffer[200]; //eventually allocate on stack
//but size have to be constant value and may be too small
proc(error_code, buffer, ret+1); // call again
MessageBoxA(0, buffer, "Return", 0); //show result
delete buffer; //free buffer!
FreeLibrary(handle);
return 0;
}
Thanks for your answer. It is a shame, that this cannot be handled differently as not everyone has that much control over their Dlls. (It could be a third party dll, in which case that would be it). We followed your instructions and managed to make it work that way.
– Pete
Nov 12 at 18:45
add a comment |
up vote
1
down vote
accepted
How do I call this function properly?
As interop? you can't ... it is also error prone in plain C++
you should rather do it like
extern "C" __declspec(dllexport) int __stdcall function(int16_t error_code,
LPSTR buffer, size_t size)
{
LPCSTR format = "error: %i";
size_t req = _scprintf(format, error_code); // check for require size
if (req > size) //buffer size is too small
{
return req; //return required size
}
sprintf_s(buffer, size, format, error_code); //fill buffer
return 0;
}
And usage
class Program
{
static void Main(string args)
{
short error_code = -10210;
var ret = function(error_code, null, 0); // check for required size of the buffer
var sb = new StringBuilder(ret); // create large enough buffer
ret = function(error_code, sb, (uint)sb.Capacity + 1); //call again
var error_desc = sb.ToString(); //get results
Console.WriteLine(error_desc);
Console.ReadKey();
}
[DllImport("TestDll.dll", EntryPoint = "function", CharSet = CharSet.Ansi)]
public static extern int function(short error_code, StringBuilder sb, int size);
}
usage in C++
typedef int (__stdcall *function)(int16_t error_code, LPSTR buffer, size_t size);
int main()
{
auto handle = LoadLibrary(L"TestDll.dll");
auto proc = (function)GetProcAddress(handle, "_function@12");
// of course it can be done via linking
int16_t error_code = 333;
const int ret = proc(error_code, NULL, 0); // check for size
CHAR* buffer = new CHAR[ret + 1];
//CHAR buffer[200]; //eventually allocate on stack
//but size have to be constant value and may be too small
proc(error_code, buffer, ret+1); // call again
MessageBoxA(0, buffer, "Return", 0); //show result
delete buffer; //free buffer!
FreeLibrary(handle);
return 0;
}
Thanks for your answer. It is a shame, that this cannot be handled differently as not everyone has that much control over their Dlls. (It could be a third party dll, in which case that would be it). We followed your instructions and managed to make it work that way.
– Pete
Nov 12 at 18:45
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
How do I call this function properly?
As interop? you can't ... it is also error prone in plain C++
you should rather do it like
extern "C" __declspec(dllexport) int __stdcall function(int16_t error_code,
LPSTR buffer, size_t size)
{
LPCSTR format = "error: %i";
size_t req = _scprintf(format, error_code); // check for require size
if (req > size) //buffer size is too small
{
return req; //return required size
}
sprintf_s(buffer, size, format, error_code); //fill buffer
return 0;
}
And usage
class Program
{
static void Main(string args)
{
short error_code = -10210;
var ret = function(error_code, null, 0); // check for required size of the buffer
var sb = new StringBuilder(ret); // create large enough buffer
ret = function(error_code, sb, (uint)sb.Capacity + 1); //call again
var error_desc = sb.ToString(); //get results
Console.WriteLine(error_desc);
Console.ReadKey();
}
[DllImport("TestDll.dll", EntryPoint = "function", CharSet = CharSet.Ansi)]
public static extern int function(short error_code, StringBuilder sb, int size);
}
usage in C++
typedef int (__stdcall *function)(int16_t error_code, LPSTR buffer, size_t size);
int main()
{
auto handle = LoadLibrary(L"TestDll.dll");
auto proc = (function)GetProcAddress(handle, "_function@12");
// of course it can be done via linking
int16_t error_code = 333;
const int ret = proc(error_code, NULL, 0); // check for size
CHAR* buffer = new CHAR[ret + 1];
//CHAR buffer[200]; //eventually allocate on stack
//but size have to be constant value and may be too small
proc(error_code, buffer, ret+1); // call again
MessageBoxA(0, buffer, "Return", 0); //show result
delete buffer; //free buffer!
FreeLibrary(handle);
return 0;
}
How do I call this function properly?
As interop? you can't ... it is also error prone in plain C++
you should rather do it like
extern "C" __declspec(dllexport) int __stdcall function(int16_t error_code,
LPSTR buffer, size_t size)
{
LPCSTR format = "error: %i";
size_t req = _scprintf(format, error_code); // check for require size
if (req > size) //buffer size is too small
{
return req; //return required size
}
sprintf_s(buffer, size, format, error_code); //fill buffer
return 0;
}
And usage
class Program
{
static void Main(string args)
{
short error_code = -10210;
var ret = function(error_code, null, 0); // check for required size of the buffer
var sb = new StringBuilder(ret); // create large enough buffer
ret = function(error_code, sb, (uint)sb.Capacity + 1); //call again
var error_desc = sb.ToString(); //get results
Console.WriteLine(error_desc);
Console.ReadKey();
}
[DllImport("TestDll.dll", EntryPoint = "function", CharSet = CharSet.Ansi)]
public static extern int function(short error_code, StringBuilder sb, int size);
}
usage in C++
typedef int (__stdcall *function)(int16_t error_code, LPSTR buffer, size_t size);
int main()
{
auto handle = LoadLibrary(L"TestDll.dll");
auto proc = (function)GetProcAddress(handle, "_function@12");
// of course it can be done via linking
int16_t error_code = 333;
const int ret = proc(error_code, NULL, 0); // check for size
CHAR* buffer = new CHAR[ret + 1];
//CHAR buffer[200]; //eventually allocate on stack
//but size have to be constant value and may be too small
proc(error_code, buffer, ret+1); // call again
MessageBoxA(0, buffer, "Return", 0); //show result
delete buffer; //free buffer!
FreeLibrary(handle);
return 0;
}
edited Nov 8 at 11:02
answered Nov 8 at 3:14
Selvin
6,31622737
6,31622737
Thanks for your answer. It is a shame, that this cannot be handled differently as not everyone has that much control over their Dlls. (It could be a third party dll, in which case that would be it). We followed your instructions and managed to make it work that way.
– Pete
Nov 12 at 18:45
add a comment |
Thanks for your answer. It is a shame, that this cannot be handled differently as not everyone has that much control over their Dlls. (It could be a third party dll, in which case that would be it). We followed your instructions and managed to make it work that way.
– Pete
Nov 12 at 18:45
Thanks for your answer. It is a shame, that this cannot be handled differently as not everyone has that much control over their Dlls. (It could be a third party dll, in which case that would be it). We followed your instructions and managed to make it work that way.
– Pete
Nov 12 at 18:45
Thanks for your answer. It is a shame, that this cannot be handled differently as not everyone has that much control over their Dlls. (It could be a third party dll, in which case that would be it). We followed your instructions and managed to make it work that way.
– Pete
Nov 12 at 18:45
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53198213%2fcalling-c-function-with-lpstr-return-value-from-c-sharp%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
How
functionis implemented? Most important is how you are allocating return value– Selvin
Nov 7 at 21:47
I read that you will need to defined export with an extern "C" block like this: extern "C" __declspec(dllexport) int captureCamera(int& captureId) { ... }
– Brian Clink
Nov 7 at 22:00
0x80000003 is E_INVALIDARG. Now, i obviously don't know which piece of the native code executed by that DLL function causes the error; but start with verifying whether the function you call actually "understands" the value
-10210(i.e., does a corresponding error message/text string exist for this particular value?)– elgonzo
Nov 7 at 22:01