C#调用C++ DLL函数返回值错误

honglian 2011-07-06 03:03:06
现有一个C++生成的DLL(别人写的,我没有源码),函数原型是这样的:

DWORD __stdcall VCI_OpenDevice(DWORD DeviceType,DWORD DeviceInd,DWORD Reserved);

我在C#中的调用如下:

namespace testPCI5110DLL
{
public partial class Form1 : Form
{
[DllImport("ControlCAN.dll")]
static private extern int VCI_OpenDevice(int DeviceType, int DeviceInd, int Reserved);

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
int open_device = VCI_OpenDevice(7, 0, 0);
if (open_device != 1)
{
MessageBox.Show("Open device fail!");
}
}
}
}

我用VC6.0调用该DLL,VCI_OpenDevice返回的值是1,但是用C#返回的却是0,1才是正确的,请问各位,问题出在哪里了?是不是参数类型转换有问题啊?还是别的原因?
...全文
982 50 打赏 收藏 转发到动态 举报
写回复
用AI写文章
50 条回复
切换为时间正序
请发表友善的回复…
发表回复
sdl2005lyx 2011-07-18
  • 打赏
  • 举报
回复
LZ可以好好总结一下,互操作常出现的错误,对以后此类问题很有帮助!
honglian 2011-07-11
  • 打赏
  • 举报
回复
[Quote=引用 48 楼 soaringbird 的回复:]
咋回事?怎么解决的?楼主说说看。
[/Quote]
呵呵,说出来惭愧啊,C#调用不成功是因为,我需要调用的ControlCAN.dll还调用了其他的DLL,问题就出在我将其他的DLL的路径搞错了,例如,供应商给我了一个Lib的文件夹,里面有ControlCAN.dll和另外一个文件夹,那个文件夹下有两个DLL,我将三个DLL放在同一层目录,即放在了我的应用程序的Debug下,调用就有问题了,error返回的是1008,将Lib下的东西直接拷贝到Debug下运行就没有问题了,C++那边调用也是这个问题。最近做了好多调用DLL的工作,不同平台和语言之间调用方式都有点不一样,现在感觉有点混乱了。
soaringbird 2011-07-11
  • 打赏
  • 举报
回复
咋回事?怎么解决的?楼主说说看。
honglian 2011-07-11
  • 打赏
  • 举报
回复
多谢各位的热心解答,问题解决了,结贴!
  • 打赏
  • 举报
回复
用c++再封装一层,我也遇见过这样的问题。应该是c++和C#互操作时数据类型的问题。
systerm 2011-07-09
  • 打赏
  • 举报
回复
你这dll肯定有问题。
honglian 2011-07-09
  • 打赏
  • 举报
回复
或者用VC2008怎样静态调用VC6.0的DLL?加载.lib和.h文件为什么不能直接调用,VC2008工程不是托管的
honglian 2011-07-09
  • 打赏
  • 举报
回复
[Quote=引用 42 楼 whycom 的回复:]
引用 40 楼 mjp1234airen4385 的回复:

看看约定的调用方式,VC的如果不修改的话,一般是cdecl。
因此[DllImportAttribute("ControlCAN.dll", EntryPoint="VCI_OpenDevice", CallingConvention=CallingConvention.StdCall)]

CallingConvention……
[/Quote]
现在VC6.0和VC2008都可以调用ControlCAN.dll了,VC6.0的代码如下:

int error = 0;
//test pci5110
//ÉùÃ÷DLLº¯Êý
typedef DWORD (CALLBACK *OPENDEVICE)(DWORD DeviceType,DWORD DeviceInd,DWORD Reserved);

//ÉùÃ÷º¯Êý¾ä±ú
HMODULE hTestDLL = NULL;
OPENDEVICE VCI_OpenDevice = NULL;

// ¼ÓÔض¯Ì¬Á´½Ó¿â
hTestDLL = LoadLibrary(TEXT("ControlCAN.dll"));
if(hTestDLL == NULL)
{
error = GetLastError();
printf("cannot load ControlCAN.dll\n");
exit(0);
}


//ϵͳÃû³Æ
VCI_OpenDevice = (OPENDEVICE)GetProcAddress(hTestDLL,"VCI_OpenDevice");
if(VCI_OpenDevice==NULL)
{
error = GetLastError();
printf("cannot load process GetHostName\n");
FreeLibrary(hTestDLL);
exit(1);
}

DWORD DeviceType = 7;
DWORD DeviceInd = 0;
DWORD Reserved = 0;
DWORD open_device_status = (*VCI_OpenDevice)(DeviceType, DeviceInd, Reserved);
error = GetLastError(); //error返回6 FreeLibrary(hTestDLL);

现在的问题是最后一次调用GetLastError返回的是6--句柄无效,我到底哪里搞错了?请高手指教。
内存溢出 2011-07-08
  • 打赏
  • 举报
回复
学习一下了
stonespace 2011-07-08
  • 打赏
  • 举报
回复
可以用vc6写一个转接dll,c#调用用vc6自己写的dll的函数,然后vc6写的这个函数再调用厂家的dll,

在自己写得dll中可以输出传递的参数和返回值,
whycom 2011-07-08
  • 打赏
  • 举报
回复
[Quote=引用 40 楼 mjp1234airen4385 的回复:]

看看约定的调用方式,VC的如果不修改的话,一般是cdecl。
因此[DllImportAttribute("ControlCAN.dll", EntryPoint="VCI_OpenDevice", CallingConvention=CallingConvention.StdCall)]

CallingConvention.StdCall要修改成Cdecl
[/Quote]
呵呵正好说反了
StdCall 被调用方清理堆栈。这是使用平台 invoke 调用非托管函数的默认约定。
----- msdn
honglian 2011-07-08
  • 打赏
  • 举报
回复
我现在只想用VC.NET调用了,VC6.0动态调用没有问题,为什么总是.NET调用有问题?
mjp1234airen4385 2011-07-08
  • 打赏
  • 举报
回复
看看约定的调用方式,VC的如果不修改的话,一般是cdecl。
因此[DllImportAttribute("ControlCAN.dll", EntryPoint="VCI_OpenDevice", CallingConvention=CallingConvention.StdCall)]

CallingConvention.StdCall要修改成Cdecl
honglian 2011-07-08
  • 打赏
  • 举报
回复
UP!高手快来帮忙啊,VC.NET调用该DLL,哪里出错了?
honglian 2011-07-08
  • 打赏
  • 举报
回复
悲剧了,我现在想用VC.NET调用,都调不了,代码如下,请各位帮我分析下:

{
//test pci5110
//声明DLL函数
typedef DWORD (_cdecl *OPENDEVICE)(DWORD DeviceType,DWORD DeviceInd,DWORD Reserved);

//声明函数句柄
HMODULE hTestDLL = NULL;
OPENDEVICE VCI_OpenDevice = NULL;

// 加载动态链接库
hTestDLL = LoadLibrary(LPCWSTR("ControlCAN.dll"));
if(hTestDLL == NULL)
{
int i = GetLastError();
printf("cannot load ControlCAN.dll\n");
exit(0);
}


//系统名称
VCI_OpenDevice = (OPENDEVICE)GetProcAddress(hTestDLL,"VCI_OpenDevice");
if(VCI_OpenDevice==NULL)
{
printf("cannot load process GetHostName\n");
FreeLibrary(hTestDLL);
exit(1);
}

DWORD open_device_status = (*VCI_OpenDevice)(7, 0, 0);

}

调用GetLastError()返回的是126--找不到指定的模块,ControlCAN.dll在该工程的Debug目录下,到底哪里出错了?
stonespace 2011-07-07
  • 打赏
  • 举报
回复
你能修改dll的代码吗?如果可以,在VCI_OpenDevice内部用MessageBox输出传入的参数数值,还有即将返回的返回值,如果不好打开界面,可以在VCI_OpenDevice内部把参数值和返回值写入文本文件,

怀疑是参数传递不成功,
honglian 2011-07-07
  • 打赏
  • 举报
回复
各位大侠救命啊!还是不能正常调用,有没有别的方法或思路?现在被卡在这里了,问题解决了追加分啊
dreamrising 2011-07-07
  • 打赏
  • 举报
回复
用uint对应WORD就应该没有问题,如果返回值不正确的话,就已经不是编程调用函数的语言性问题了,得想想设备操作方面的。
bloodish 2011-07-07
  • 打赏
  • 举报
回复
你们既然有头文件,又有库文件,何必拽着PInvoke不放?
用C++/CLI封装一层才是最佳的选择.
  • 打赏
  • 举报
回复
引用 31 楼 stonespace 的回复:
你能修改dll的代码吗?如果可以,在VCI_OpenDevice内部用MessageBox输出传入的参数数值,还有即将返回的返回值,如果不好打开界面,可以在VCI_OpenDevice内部把参数值和返回值写入文本文件,

怀疑是参数传递不成功,


DLL是别的公司提供的,我没有源码
加载更多回复(30)

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧