从C++、C#和Ruby中调用C DLL

9

你好,我有一个DLL文件需要调用其中的一个函数。该函数的签名如下:

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

如果我使用 Ruby,一切正常:
attach_function :callMethod, [:string, :string], :string

如果我使用C++或C#,我会遇到堆栈溢出的问题!?
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", "{}");

我尝试了很多调用函数的方式: WINAPI、PASCAL、stdcall、fastcall等,但都没有成功。

这个DLL不是我制作的,我无法控制它。

有没有人能给我任何建议呢?


您可以看一下我的问题以了解情况。这是一个链接 - Sergey Kucher
2
为什么不在C#中使用string作为这两个参数的类型? - Ove
相信我,我已经搜索了很多…… :)。我也尝试过使用字符串,但为了避免C#问题,我还尝试了老好的C++,但仍然出现堆栈溢出! - Joao
4个回答

1

1

这只是一个想法,但据我所知,这可能与空终止字符串有关。 const char* myvar 是以空字符结尾的,但字节数组不是。你需要做的就是将调用更改为 ...(String a, String b) 并将它们作为 LPStr 进行编组。


堆栈溢出异常! - Joao
@Joao 我确定错误不是由调用本身引起的(我确定上面的调用是正确的),可能是你调用的方法出现了错误,因为当堆栈上有太多数据时会生成堆栈溢出,这可能有很多原因。 - Felix K.
是的,您说得对。但令我困扰的是 Ruby 能够正常工作……我并不是很了解 Ruby,我在考虑可能存在 Ruby 调用和 C++ 或 C# 调用之间的一些根本性差异导致了这种情况。另一个问题可能是某些编译器选项。 - Joao
@Joao请检查您正在使用的字符集(ASCII,Unicode),也许这是导致错误的原因。 - Felix K.
@Joao,没有C++库的任何代码,很难找出问题出在哪里。我认为这与C#代码无关。也许你应该看看Ruby是如何做的。 - Felix K.

0

我认为你完全可以更改你的调用方式:

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

你需要发送指针而不是实际值/字节到函数中。
当我生成本地函数调用的类型转换时,我总是使用这个mapping
对于C++代码也是一样,你需要创建包含内容的变量,然后调用该函数。


同样的事情!系统堆栈溢出异常 - Joao
你能展示一下你改过的代码吗?另外,我会使用 http://www.dependencywalker.com/ 来检查依赖问题。 - weismat
我已经按照你的代码片段进行了操作,并尝试使用[MarshalAs(UnmanagedType.LPStr)]。我的调用方式是response = callMethod(key, args); 其中key和args的类型为字符串。 - Joao
你也在使用相同参数调用该方法吗?或者编写一个虚拟的dll,只打印参数,以便您可以隔离错误。可能是在调用错误参数时,该dll已经损坏了。 - weismat
嗨,我已经完成了。然后我调用了Ruby,并在DLL中编写了接收到的字节,结果与预期相同! - Joao
显示剩余2条评论

-5

Stack Overflow Exception是一种在Microsoft语言中用来防止无限递归和防止不兼容程序相互交互的错误。如果您的dll方法使用了递归,请尝试使用迭代进行重写。否则,像Ove所说的那样,尝试使用字符串。如果仍然无法解决问题,请搜索兼容类型。这就是我在不知道实际方法的情况下能够提供的所有信息。


“堆栈溢出异常”是微软语言中的一种错误,用于防止无限递归,并防止不兼容的程序相互交互。您从哪里得到这个想法的?在我所知道的任何平台上都可能发生堆栈溢出... - ildjarn
简单,我在谷歌搜索解决自己的问题时在微软网站上读到了它。解决方案是改为迭代式。 - m12
我的观点是这并不特定针对微软的语言/平台,也不是为了防止不兼容的程序彼此交互(有时是由于不兼容的程序相互作用而引起的)。 - ildjarn
这个DLL不是我制作的,我对它没有任何控制权。我不知道这个方法的源代码! - Joao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接