VB调用C写的DLL

yuanxilin 2007-12-17 11:04:59
有一个C写的DLL
int RunSeries(unsigned char* lpszScrColorImg, int height,int width,int mode, LEUCCYTO1 LeucChar[]);
LEUCCYTO1 是一个结构体。
typedef struct {
double NucRough;
double cytcolor;
double diffr;
double CytoRoundness;
double CellSize;
double NucRoundness;
double NucRoundnessD;
double NucRoundnessM;
double NucSizeRate;
double discrimNuc;
double discrimCyto;
int x;
int y;
int NucCount;
int NucTotalPixel;
int MaxNuc;
int NucDiff;
int CellTotalPixel;
int size;
int meanr;
int maxr;
int minr;
int seedl;
int cellclass;
unsigned char rgb[3];
BOOL aciDoubt;
int bw_1;
}LEUCCYTO1;
在C中调用语句

unsigned char buff[1024 * 768 * 3];
cell_num = RunSeries((unsigned char*)buff, height,width,0,LeucChar1);

现在用VB 调用
Public Type LEUCCYTO1
NucRough As Double
cytcolor As Double
diffr As Double
CytoRoundness As Double
CellSize As Double
NucRoundness As Double
NucRoundnessD As Double
NucRoundnessM As Double
NucSizeRate As Double
discrimNuc As Double
discrimCyto As Double
x As Long
y As Long
NucCount As Long
NucTotalPixel As Long
MaxNuc As Long
NucDiff As Long
CellTotalPixel As Long
size As Long
meanr As Long
maxr As Long
minr As Long
seedl As Long
cellclass As Long
rgb(1 To 3) As Byte
aciDoubt As Long
bw_1 As Long
End Type

Declare Function RunSeries Lib "C:\sbtx\HemanalyDll4.dll" (ByRef lpszScrColorImg As String, ByRef height As Long, ByRef width As Long, ByRef mode As Long, ByRef LeucChar() As LEUCCYTO1) As Long

调用语句
Dim KK As String
KK = String(2359297, Chr(0))
I = RunSeries(KK, 768, 1024, 0, LeucChar1)

一直运行不了,报“VB 遇到问题需要关闭”,请高手帮忙看下是那里出了问题。
...全文
304 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuanxilin 2007-12-24
  • 打赏
  • 举报
回复
多谢Tiger_Zhao ,of123 ,问题解决了,是如of123 说的没加__stdcall。我以前一直以为他加了的,晕
Tiger_Zhao 2007-12-19
  • 打赏
  • 举报
回复
VB调用代码请再发一次,收到rar长度为零。
yuanxilin 2007-12-19
  • 打赏
  • 举报
回复
不是调用规约的问题,这个已经写为了__stdcall
of123 2007-12-18
  • 打赏
  • 举报
回复
不行,你的函数调用规约不是 __stdcall,VB 不能直接支持。

int RunSeries(unsigned char* lpszScrColorImg, int height,int width,int mode, LEUCCYTO1 LeucChar[]);

一种方法是再写一个 C 的 DLL, 用一个 __stdcall 函数间接调用 RunSeries.

还有,就是比较麻烦的方法,写一个类来调用 __Cdecl 函数。下面是一个例子:

Imports System
Imports Microsoft.VisualBasic
Imports System.Runtime.InteropServices
Public Class LibWrap
' Visual Basic does not support varargs, so all arguments must be
' explicitly defined. CallingConvention.Cdecl must be used since the stack
' is cleaned up by the caller.
' int printf( const char *format [, argument]... )
<DllImport("msvcrt.dll", CallingConvention := CallingConvention.Cdecl)> _
Overloads Shared Function printf ( _
format As String, i As Integer, d As Double) As Integer
End Function
<DllImport("msvcrt.dll", CallingConvention := CallingConvention.Cdecl)> _
Overloads Shared Function printf ( _
format As String, i As Integer, s As String) As Integer
End Function
End Class 'LibWrap
Public Class App
Public Shared Sub Main()
LibWrap.printf(ControlChars.CrLf + "Print params: %i %f", 99,
99.99)
LibWrap.printf(ControlChars.CrLf + "Print params: %i %s", 99, _
"abcd")
End Sub 'Main
End Class 'App
yuanxilin 2007-12-18
  • 打赏
  • 举报
回复
Tiger_Zhao ,我 已经将正常调用DLL的VC代码,以及我自己写的VB代码发往你的EMAIL了
yuanxilin 2007-12-18
  • 打赏
  • 举报
回复
Tiger_Zhao ,我 已经将正常调用DLL的VC代码,以及我自己写的VB代码发往你的EMAIL了
yuanxilin 2007-12-17
  • 打赏
  • 举报
回复
dll是别人写好的,封装了的,应该加了_stdcall修饰符。
LeucChar 在他的C代码例子里是
LEUCCYTO1 LeucChar1[400];
我在VB里用了
Dim LeucChar1() As LEUCCYTO1
ReDim LeucChar1(0 To 399)
For I = 0 To 399
LeucChar1(I).aciDoubt = 1
Next I
来保证内存的分配
CamelFang 2007-12-17
  • 打赏
  • 举报
回复
在dll中将RunSeries函数加上_stdcall修饰符试试.
yuanxilin 2007-12-17
  • 打赏
  • 举报
回复
声明修改为:
Declare Function RunSeries Lib "HemanalyDll4.dll" (ByRef lpszScrColorImg() As Byte, ByVal height As Long, ByVal width As Long, ByVal mode As Long, ByRef lpLeucChar() As LEUCCYTO1) As Long

调用改为
I = RunSeries(buff, 768, 1024, 0, LeucChar1)

结果报内存错误,说不能读取0X00000008
  • 打赏
  • 举报
回复
lpszScrColorImg() As byte
lpLeucChar() As LEUCCYTO1

试一下这两个参数改成数组呢?
yuanxilin 2007-12-17
  • 打赏
  • 举报
回复
非常感谢Tiger_Zhao 的指导,但还是运行不了,报“实时错误49 DLL调用约定错误”
Tiger_Zhao 2007-12-17
  • 打赏
  • 举报
回复
int RunSeries(unsigned char* lpszScrColorImg, int height,int width,int mode, LEUCCYTO1 LeucChar[]); 
//参数 LeucChar 作为数组,数组由谁创建?数组长度多少?

typedef struct {
...
unsigned char rgb[3]; //数组长度为4
...
}LEUCCYTO1;


Public Type LEUCCYTO1
...
rgb(0 To 3) As Byte '长度要一致,下标遵循C标准比较方便
...
End Type

'注:VB中不支持语句内注释,使用时将下面的注释去除后拼成一句
Declare Function RunSeries Lib "HemanalyDll4.dll" '尽量不用绝对路径,只有保证dll在exe同目录或系统目录下就可以了
( ByRef lpszScrColorImg As byte, '传递字节数组用这种定义比较方便
ByVal height As Long, ByVal width As Long, ByVal mode As Long, '传值一律用 ByVal
ByRef lpLeucChar As LEUCCYTO1 '假定该数组由调用者创建,长度已约定
) As Long

'调用
dim buff(0 to 2359296-1) as byte
dim LeucChar1(0 to 约定长度-1) as LEUCCYTO1
I = RunSeries(buff(0), 768, 1024, 0, LeucChar1(0)) '注意:用Byref的声明和采用数组首元素作为参数,对应C中的指针/数组
嗷嗷叫的老马 2007-12-17
  • 打赏
  • 举报
回复
再路过一下......
yuanxilin 2007-12-17
  • 打赏
  • 举报
回复
如果需要DLL的话加我QQ:6258323,我一直隐身的。
zzyong00 2007-12-17
  • 打赏
  • 举报
回复
Declare Function RunSeries Lib "HemanalyDll4.dll" _
( ByVal lpszScrColorImg As Long, _
ByVal height As Long, ByVal width As Long, ByVal mode As Long, _
ByVal lpLeucChar As Long _
) As Long


如果这样的声明都有错,哪真是奇了
  • 打赏
  • 举报
回复
把LeucChar1声明成Byte型动态数组,先看看接口的数据能进来吗?
yuanxilin 2007-12-17
  • 打赏
  • 举报
回复
汗,VC以前都没怎么用过的。救命呀
Tiger_Zhao 2007-12-17
  • 打赏
  • 举报
回复
你改用VC作一下调用测试,怀疑参数格式或数据类型(32位、64位)不一致。
yuanxilin 2007-12-17
  • 打赏
  • 举报
回复
for(i=0; i <width*height; i++)
{
buff[i ] = 0;
}
部分改为

for(i=0; i <width*height; i++)
{
buff[i * 3] = 0;
buff[i*3+1] = 0;
buff[i*3+2] = 0;
}
嗷嗷叫的老马 2007-12-17
  • 打赏
  • 举报
回复
我也来凑凑热闹......
加载更多回复(8)

1,486

社区成员

发帖
与我相关
我的任务
社区描述
VB API
社区管理员
  • API
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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