dll工程中导出函数的问题

chenxiaoguo 2009-08-10 10:56:17
Q1:

sha()函数在sha.cpp中
Lib.cpp中
void callsha(unsigned char *buf, int len, unsigned char *hash);
Lib.h中
#include "sha.h"
__declspec(dllexport)
void callsha(unsigned char *buf, int len, unsigned char *hash);

这样写对不对?有什么问题吗?


Q2:

在C#中调用该函数
[DllImport("Lib.dll", EntryPoint = "callsha", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern void callsha(ref byte[] buf, int len, ref byte[] hash);
使用时:
byte[] P = new byte[64];
byte[] hash = new byte[32];
sha1(P, 64, ref hash);

运行时出现以下错误:
The runtime has encountered a fatal error. The address of the error was at 0x79e7c5eb, on thread 0x964. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

是C#代码的原因还是因为上面的dll有问题?

谢谢各位
...全文
229 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
hallowwar 2009-09-18
  • 打赏
  • 举报
回复
好贴,学习必顶!!!
chenxiaoguo 2009-08-13
  • 打赏
  • 举报
回复
自己up一下
skyair624 2009-08-12
  • 打赏
  • 举报
回复
__declspec(dllimport)呢,没有的话你这个头文件怎么在需要导入此dll的工程声明,要么.def

还有1楼,extern "C"
这里用C的方式编译不是问题所在,如果加上在LINK这个导入的时候反而还要声明为C的方式寻找函数,没有必要
chenxiaoguo 2009-08-12
  • 打赏
  • 举报
回复
现在的问题是只导出B之后在C#中调用再运行就会出现题目中的错误,但是单独导出A(不导出B),在C#中重新写函数调用A实现B的功能就不会出错,想不明白为什么,给解释下原因吧,谢谢
socoola 2009-08-11
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 chenxiaoguo 的回复:]
谢谢各位
dll里有一个静态函数A,函数B多次调用A,怎么导出?
[/Quote]
导出B就是,不用导出A。
chenxiaoguo 2009-08-11
  • 打赏
  • 举报
回复
谢谢各位
dll里有一个静态函数A,函数B多次调用A,怎么导出?
socoola 2009-08-10
  • 打赏
  • 举报
回复
函数的声明和实现要一致
socoola 2009-08-10
  • 打赏
  • 举报
回复
头文件声明:
#define SHA_API __declspec(dllexport)

SHA_API void callsha(unsigned char *buf, int len, unsigned char *hash);

c文件定义:
SHA_API void callsha(unsigned char *buf, int len, unsigned char *hash)
{
........
}
zhoujianhei 2009-08-10
  • 打赏
  • 举报
回复
.h
extern "C" __declspec(dllexport)
void callsha(unsigned char *buf, int len, unsigned char *hash);

.cpp
void __stdcall callsha(unsigned char *buf, int len, unsigned char *hash)

试试。
paerxiushi 2009-08-10
  • 打赏
  • 举报
回复
调用代码改成:
typedef int (_stdcall *lpStdAdd)(int a,int b);
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE lpDll=LoadLibrary(L"D:\\文档\\程序\\C++程序\\Windows编程\\StdDll\\debug\\StdDll.dll");
if(lpDll)
{
lpStdAdd add=(lpStdAdd)GetProcAddress(lpDll,"add");
if(!add) return 0;
int a=0;
a=add(5,6);
cout < <a < <endl;
cin>>a;
if(!FreeLibrary(lpDll))
{
MessageBox(NULL,L"DLL释放失败",L"消息",MB_OK);
}
}
return 0;
}
paerxiushi 2009-08-10
  • 打赏
  • 举报
回复
1.先定义一个DEF文件,将函数导出:

在def文件中加入如下代码:
LIBRARY "StdDll" //其中"StdDll"是Dll工程的名称
EXPORTS
;以下是函数列表
add @ 1 //add是函数名,@后面是函数的序号
当采用h头文件方式导出函数生成Dll时,其调用函数在调用方被转义,其名字形如:输出函数名前面加下划线,后面加“@”符号和参数的字节数。那么函数add在调用时需要写成"_add@8";可以看出add函数前加_,然后在函数名后加@,因为该函数使用两个整数做为参数时,那么参数总大小为8字节。
而采用def加序号来声明函数,调用方就可以直接引用函数原名。

2.在cpp文件中加入如下代码:
#include "stdafx.h"
#include "StdDll.h"
int _stdcall add(int a,int b)
{
int c=0;
c=a+b;
return c;
}

3.调用方的代码如下:
那么应用程序的调用代码应该改成:
typedef int (*lpStdAdd)(int a,int b);
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE lpDll=LoadLibrary(L"D:\\文档\\程序\\C++程序\\Windows编程\\StdDll\\debug\\StdDll.dll");
if(lpDll)
{
lpStdAdd add=(lpStdAdd)GetProcAddress(lpDll,"add");
if(!add) return 0;
int a=0;
a=add(5,6);
cout<<a<<endl;
cin>>a;
if(!FreeLibrary(lpDll))
{
MessageBox(NULL,L"DLL释放失败",L"消息",MB_OK);
}
}
return 0;
}
chenxiaoguo 2009-08-10
  • 打赏
  • 举报
回复
是这样,这个dll中还有其他的导出函数,目前都可以调用成功,只有这个函数会出这样的问题……所以感觉不知道该从哪儿开始下手了,唉
jingzhongrong 2009-08-10
  • 打赏
  • 举报
回复
你在C#中用CallingConvention.StdCall调用方式,而DLL中的函数却不是stdcall的,将dll中的函数声明为stdcall的,用def文件导出函数。
qqiuzaihui 2009-08-10
  • 打赏
  • 举报
回复
/*** 测试程序(MFC程序, C#中也是一样的, 定义一个类似的结构体, 传入就行了.) ***/
1. 在头文件中声明一个结构体:
struct _MY_CUSTOM_
{
int result;
double circle;
char* version;
};

2. 创建一个结构体实例:
struct _MY_CUSTOM_ myCustom;

3. 测试代码:
HINSTANCE hInst = LoadLibrary("HmPark.dll");
typedef _MY_CUSTOM_ (CALLBACK *ADDPROC)(int type, char* name, char* product);
ADDPROC MyCustomFunction = (ADDPROC)GetProcAddress(hInst, "MyCustomFunction");

if( !MyCustomFunction )
{
MessageBox("找不到动态库");
return;
}

char* name = "my";
char* product = "custom";
int type = 5;
CString str;

try
{
myCustom = MyCustomFunction(type, name, product);
}
catch(...)
{
MessageBox("Error");
}

str.Format("\n%d, %f, %s.\n", myCustom.result, myCustom.circle, myCustom.version );
MessageBox( str );

4. 输出结果: 5, 10.000000, my.
qqiuzaihui 2009-08-10
  • 打赏
  • 举报
回复
感觉是你的DLL文件写的不对, 前段时间写了一个, 仅供参考:

/***************************** ParkLib.def 文件内容 ***************************/
; ParkLib.def : Declares the module parameters for the DLL.

LIBRARY "ParkLib"
DESCRIPTION 'ParkLib Windows Dynamic Link Library'

EXPORTS
; Explicit exports can go here
MyCustomFunction





/****************************** ParkLib.h 文件内容 ***************************/
/*--------------------------------------------------------------------------
ParkLib.H header file
----------------------------------------------------------------------------*/
#ifdef __ParkStdFee
#define EXPORT extern "C" __declspec (dllexport)
#else
#define EXPORT __declspec (dllexport)
#endif

/******************************************************************************
* 自定义一个数据结构用于返回
******************************************************************************/
typedef struct
{
int result;
double circle;
char* version;
}_MY_CUSTOM_;

/******************************************************************************
* 函数功能:根据输入的 [type] ,[name] 及 [product] 返回结果
* 输 入:[type] ,[name] 及 [product]
* 返 回:_MY_CUSTOM_ 结构数据
******************************************************************************/
EXPORT _MY_CUSTOM_ CALLBACK MyCustomFunction(int type, char* name, char* product);





/***************************** ParkLib.C 文件内容 ****************************/
/*---------------------------------------------------------------------------
ParkLib.C -- Easy Drawing Routine Library module
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include "ParkLib.h"

_MY_CUSTOM_ CALLBACK MyCustomFunction(int type, char* name, char* product); //自定义函数

int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
return TRUE ;
}

EXPORT _MY_CUSTOM_ CALLBACK MyCustomFunction(int type, char* name, char* product)
{
_MY_CUSTOM_ myCustom;

myCustom.result = type;
myCustom.circle = type * 2;
myCustom.version = name;

return myCustom;
}
qqiuzaihui 2009-08-10
  • 打赏
  • 举报
回复
首先在C++中测试一下, 确保你的动态库文件是正确可调用的,
然后在C#中改用:
[DllImport("Lib.dll", EntryPoint = "callsha", CharSet = CharSet.Ansi)]
public static extern void callsha(byte[] buf, int len, byte[] hash);
试试.
wltg2001 2009-08-10
  • 打赏
  • 举报
回复
对于DLL的导出问题,我觉得最保险还是写DEF文件。
zhaohongbo83 2009-08-10
  • 打赏
  • 举报
回复
.h
extern "C" __declspec(dllexport)
void callsha(unsigned char *buf, int len, unsigned char *hash);

.cpp
void __stdcall callsha(unsigned char *buf, int len, unsigned char *hash)

__stdcall函数调用要使用这种模式!

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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