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










share|improve this question






















  • 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












  • 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















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










share|improve this question






















  • 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












  • 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













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










share|improve this question













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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 7 at 21:37









Pete

209




209












  • 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












  • 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










  • 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












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;
}





share|improve this answer























  • 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











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















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

























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;
}





share|improve this answer























  • 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















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;
}





share|improve this answer























  • 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













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;
}





share|improve this answer














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;
}






share|improve this answer














share|improve this answer



share|improve this answer








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


















  • 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


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














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





















































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







這個網誌中的熱門文章

Academy of Television Arts & Sciences

L'Équipe

1995 France bombings