有个思路,在vc6里验证了一下,你整理一下应该可用
测试程序
#include "stdafx.h"
#include <windows.h>int CallDllFun(char *pDllPath, char *pFunName, BYTE *pParam, int nSize, BOOL bHaveRetVal)
{
HINSTANCE hInst;
hInst = LoadLibrary(pDllPath);
typedef void (*ADDPROC)();
ADDPROC PROC = (ADDPROC)GetProcAddress(hInst, pFunName);
for (int i = nSize - 1; i >= 0; i--)
{
int k = *(int *)(&pParam[i * 4]);
_asm
{
push k
}
}
PROC();
if (bHaveRetVal)
{
int nRet;
_asm
{
mov nRet, eax
}
return nRet;
}
return 0;
}int main(int argc, char* argv[])
{
char *pDllPath = "E:\\Work\\CCB\\dev_bp\\testdll111\\Release\\testdll111.dll";
char *pFun1 = "Fun1";
char *pFun2 = "Fun2";
BYTE pParam[255] = "";
char *pszParam = "asdfasdf";
// 调用EXPORT1 int CALLBACK Fun1(char *pszParam)
memcpy(pParam, &pszParam, 4); // 第一个参数
int nRet = CallDllFun(pDllPath, pFun1, pParam, 1, TRUE);
int ch = 'A';
memcpy(pParam , &ch, 4); // 第一个参数char类型
int nVal = 1002;
memcpy(pParam + 4, &nVal, 4); // 第二个参数
nRet = CallDllFun(pDllPath, pFun2, pParam, 2, FALSE);
return 0;
}Dll:
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#ifdef __cplusplus
#define EXPORT1 extern "C" __declspec (dllexport)
#else
#define EXPORT1 __declspec (dllexport)
#endifEXPORT1 int CALLBACK Fun1(char *pszParam)
{
printf("%s\n", pszParam);
return 0;
}EXPORT1 void CALLBACK Fun2(char ch, int nParam)
{
printf("%c%d\n", ch, nParam);
return;
}#pragma comment(linker, "/EXPORT:Fun1=_Fun1@4,PRIVATE")
#pragma comment(linker, "/EXPORT:Fun2=_Fun2@8,PRIVATE")
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
测试程序
#include "stdafx.h"
#include <windows.h>int CallDllFun(char *pDllPath, char *pFunName, BYTE *pParam, int nSize, BOOL bHaveRetVal)
{
HINSTANCE hInst;
hInst = LoadLibrary(pDllPath);
typedef void (*ADDPROC)();
ADDPROC PROC = (ADDPROC)GetProcAddress(hInst, pFunName);
for (int i = nSize - 1; i >= 0; i--)
{
int k = *(int *)(&pParam[i * 4]);
_asm
{
push k
}
}
PROC();
if (bHaveRetVal)
{
int nRet;
_asm
{
mov nRet, eax
}
return nRet;
}
return 0;
}int main(int argc, char* argv[])
{
char *pDllPath = "E:\\Work\\CCB\\dev_bp\\testdll111\\Release\\testdll111.dll";
char *pFun1 = "Fun1";
char *pFun2 = "Fun2";
BYTE pParam[255] = "";
char *pszParam = "asdfasdf";
// 调用EXPORT1 int CALLBACK Fun1(char *pszParam)
memcpy(pParam, &pszParam, 4); // 第一个参数
int nRet = CallDllFun(pDllPath, pFun1, pParam, 1, TRUE);
int ch = 'A';
memcpy(pParam , &ch, 4); // 第一个参数char类型
int nVal = 1002;
memcpy(pParam + 4, &nVal, 4); // 第二个参数
nRet = CallDllFun(pDllPath, pFun2, pParam, 2, FALSE);
return 0;
}Dll:
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#ifdef __cplusplus
#define EXPORT1 extern "C" __declspec (dllexport)
#else
#define EXPORT1 __declspec (dllexport)
#endifEXPORT1 int CALLBACK Fun1(char *pszParam)
{
printf("%s\n", pszParam);
return 0;
}EXPORT1 void CALLBACK Fun2(char ch, int nParam)
{
printf("%c%d\n", ch, nParam);
return;
}#pragma comment(linker, "/EXPORT:Fun1=_Fun1@4,PRIVATE")
#pragma comment(linker, "/EXPORT:Fun2=_Fun2@8,PRIVATE")
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
解决方案 »
- CSplitterWnd 设置一列的最大宽度
- 如何将流数据封装成TS流,有开源的代码吗?
- 请教~关于拆分窗口后出现的问题
- 大家看看这段代码 问题出在那里
- 我得鸡年第一贴,散分,各位新年快乐!!!
- 在一个非对话框里生成控件,如何响应事件....100分
- 苦脑啊!!有什么软件可以跟踪程序的不响应任何事件的问题
- 求一思路:如何在自己的程序中装入WORD,HTM等文件,并以图形方式显示?
- WIN32API高手请进
- SendMessage,第一个参数的问题。急人啊
- <基于ADO技术的数据库类设计与实现>,谁能给点意见?谢谢
- vc 运行错误 unhandled exception in packetcapture.exe:0xc0000005:access violation
int CallDllFun(char *pDllPath, char *pFunName, BYTE *pParam, int nSize, BOOL bHaveRetVal)
{
int nRet;
HINSTANCE hInst;
hInst = LoadLibrary(pDllPath);
typedef void (*ADDPROC)();
ADDPROC PROC = (ADDPROC)GetProcAddress(hInst, pFunName);
for (int i = nSize - 1; i >= 0; i--)
{
int k = *(int *)(&pParam[i * 4]);
_asm
{
push k
}
}
PROC();
_asm
{
mov nRet, eax
}
if (bHaveRetVal)
{
return nRet;
}
return 0;
}
{
HINSTANCE hInst;
int nRet;
hInst = LoadLibrary(pDllPath);
typedef void (*ADDPROC)();
ADDPROC PROC = (ADDPROC)GetProcAddress(hInst, pFunName); //
// Make sure GetProcAddress succeed, otherwise will crash later
//
if (!PROC)
{
return GetLastError(); //ERROR_NOT_FOUND most likely.
}
for (int i = nSize - 1; i >= 0; i--)
{
int k = *(int *)(&pParam[i * 4]);
_asm
{
push k
}
}
PROC();
//Save the eax value first, we are going to use it next.
_asm
{
mov nRet, eax
}
//
// If API is of C calling convention, we need to clear the stack
//
if (bCCallingConvention)
{
__asm
{
mov eax, nSize;// 32bit system, argument * 4 should be the size to adjust
shl eax, 2;
add esp, eax;
}
} if (pRetVal)
{
*pRetVal = nRet;
} return ERROR_SUCCESS;
}我没有测试,你试一下。调用后需要检查返回值,如果不是ERROR_SUCCESS,说明失败了。API本身的返回值通过pRetVal得到。你的情况,bCCallingConvention给TRUE,如果你的函数前面有定义WINAPI或者__stdcall等等,这个传入FALSE。另外这段程序64位OS会有问题,我懒得该了,(Itaninum上根本不编译,因为用了386的汇编)。
{
int k = *(int *)(&pParam[i * 4]);
_asm
{
push k
}
} 这是不是假设了参数都是int,问题是只有运行时才知道参数是什么类型啊
{
printf("%s\n", pszParam);
return 0;
} EXPORT1 void CALLBACK Fun2(char ch, int nParam)
{
printf("%c%d\n", ch, nParam);
return;
} 三种类型的参数都有了
我想32位编译器会把8位的char扩展到32位,一个寄存器的大小