9

Hi I have a DLL with a function that I need to call. The signature is:

const char* callMethod(const char* key, const char* inParams);

If I use ruby everything works fine:

attach_function :callMethod, [:string, :string], :string

If I use C++ or C# I get stack overflow!?

C#:

[DllImport("DeviceHub.dll", CallingConvention = CallingConvention.Cdecl)]
private unsafe static extern IntPtr callMethod(
    [MarshalAs(UnmanagedType.LPArray)] byte[]  key,
    [MarshalAs(UnmanagedType.LPArray)] byte[] inParams
);

System.Text.UTF8Encoding encoding = new UTF8Encoding();
IntPtr p = callMethod(encoding.GetBytes(key), encoding.GetBytes(args)); // <- stack overflow here

c++:

extern "C"
{
typedef  DllImport const char*  (  *pICFUNC) (const char*, const char*); 
}
HINSTANCE hGetProcIDDLL = LoadLibrary(TEXT("C:\\JOAO\\Temp\\testedll\\Debug\\DeviceHub.dll"));  
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"callMethod");*      pICFUNC callMethod;
callMethod = (pICFUNC) lpfnGetProcessID;
const char * ptr = callMethod("c", "{}");

I have tried lots of variations for function calling : WINAPI, PASCAL, stdcall, fastcall,... nothing works.

The DLL has not been made by me and I have no control on it.

Can anyone help me with any suggestion!?

Joao
  • 99
  • 4
  • You can have a look at my question to have an idea. Here is a [link][1] [1]: http://stackoverflow.com/questions/7153521/pass-multi-dimensional-array-from-managed-code-to-unmanaged-code – Sergey Kucher May 03 '12 at 17:56
  • 2
    Why don't you use `string` for the types of the two parameters in C# ? – Ove May 03 '12 at 18:44
  • Believe me I have searched a lot ... :). I have also tried with strings but for the sake of avoiding c# problems I have also tested with old good c++ and still stack overflow! – Joao May 04 '12 at 07:21

4 Answers4

1

Make sure that the declaration in your header is enclosed in an extern "C" block:

extern "C" {

const char* callMethod(const char* key, const char* inParams);

}

See http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.3

Gort the Robot
  • 2,329
  • 16
  • 21
1

This is just a idea but AFAIK this might be a issue with null-terminated strings, const char* myvar is null-terminated but a byte array isn't. Everything you need to to is to change the call to ...(String a, String b) and marshal them as LPStr.

Felix K.
  • 6,201
  • 2
  • 38
  • 71
  • same thing!system.stackoverflow exception – Joao May 04 '12 at 09:07
  • @Joao I'm sure that the error is not generated by the call itself( I'm sure the call above is correct ), there might be a error in the method you call because a stack-overflow is generated when do much data is on the stack, this can have many reasons. – Felix K. May 04 '12 at 09:16
  • yes you are right. but the thing that annoys me is the fact that ruby works ... I nod not know ruby very well and I am considering the possibility that there are some fundamental differences between ruby call and c++ or c# call that makes this happening. Another issue is maybe some compiler option. – Joao May 04 '12 at 09:28
  • @Joao Check the charset ( ASCII, Unicode ) you are using, maybe this causes the error. – Felix K. May 04 '12 at 12:31
  • @Joao It's hard to find out what's going wrong here without any code of the c++ lib. I don't think that it has anything to do with the C# code. Maybe you should look how ruby is doing it. – Felix K. May 11 '12 at 09:08
0

I see no reason why you should not change your call to

[DllImport("DeviceHub.dll", CallingConvention = CallingConvention.Cdecl)]
private unsafe static extern string callMethod(
string key,
string inParams
);

You need to send pointers, not actual values/bytes to the function.
I always use this mapping when generating the type conversion for native function calls.
Same applies for the c++ code, you need create variables with the content and call the function then.

weismat
  • 7,195
  • 3
  • 43
  • 58
  • same thing! system.stackoverflow exception – Joao May 04 '12 at 09:08
  • Could you show your changed code? Also I would use http://www.dependencywalker.com/ to check for dependeny issues. – weismat May 04 '12 at 09:38
  • I have done exactly as your code fragment and also tried with [MarshalAs(UnmanagedType.LPStr)]. The way I am calling is response = callMethod(key, args); where key and args are of type string – Joao May 04 '12 at 10:13
  • I have used dependency walker to make sure that the function call is really inside the dll. I got an error "Error: At least one module has an unresolved import due to a missing export function in an implicitly dependent module." with IESHIMS.DLL but wont that also affect ruy? – Joao May 04 '12 at 10:18
  • Depends how %PATH% is inside ruby. – weismat May 04 '12 at 10:55
  • Are you also calling the method with the same parameters. Alternatively write a dummy dll which just prints the parameters so that you can isolate the error. It might be that the dll is just broken when bad parameters are called. – weismat May 04 '12 at 11:24
  • Hi, I have done that. Then I have called ruby and within the DLL I have written the bytes received and it was as expected! – Joao May 11 '12 at 08:14
-5

Stack Overflow Exception is an error put in microsoft languages to prevent infinite recursion, and to prevent incompatible programs from interacting with each other. If your dll method uses recursion, try rewriting it with iteration. Otherwise, do as Ove said, and try with strings. If it still doesn't work, Google for a compatible type. That's all I can say without knowing the actual method.

m12
  • 31
  • 1
  • 8
  • "*Stack Overflow Exception is an error put in microsoft languages to prevent infinite recursion, and to prevent incompatible programs from interacting with each other.*" Where did you get this idea? You can overflow the stack on any platform I'm aware of... – ildjarn May 03 '12 at 23:32
  • Simple, I just read it on the microsoft website while googleing for a solution to my own problem. The solution was changing it to iterative. – m12 May 03 '12 at 23:33
  • My point is that it isn't in any way specific to Microsoft languages/platforms, nor is it there to prevent incompatible programs from interacting with each other (it is sometimes _caused by_ incompatible programs interacting with each other). – ildjarn May 03 '12 at 23:42
  • The DLL has not been made by me and I have no control on it. I do not know the method source code! – Joao May 04 '12 at 07:42