我有一个供应商应用程序,我相信是使用C或C ++构建的,并且它可以对DLL进行特定调用以允许扩展功能。我正在尝试为该dll编写POC,并且仅使用此作为规范:
extern int __stdcall LIQEXIT3_LoadCustomer(const char* name, char* id);
我应该能够传入一个char *名称,然后在id字段中返回相同的char *。不幸的是,这不是正在发生的事情。我要么获得访问冲突,要么一切正常,但调用应用程序不会在ID字段中获取新信息。
我创建了以下DLL和头文件代码: TestDLL.h
#ifdef TestDLL_EXPORTS
#define TestDLL_API __declspec(dllexport)
#else
#define TestDLL_API __declspec(dllimport)
#endif
namespace TestDLL
{
class TestDLL
{
public:
static int __declspec(dllexport) __stdcall TestDLL::TestMethod_LoadCustomer(const char* name, char* id);
};
}
TestDLL.cpp
// TestDLL.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "TestDLL.h"
#include <string>
namespace TestDLL{
extern "C" int __declspec(dllexport) __stdcall TestDLL::TestMethod_LoadCustomer(const char* name, char* id)
{
std::string test(name);
if (test.size() <= 8) {
id = (char*)malloc(strlen(name)+1);
strcpy(id, name); // name contains customer id
} else {
id[0] = 0; // Customer not found
}
return 0;
}
}
当我对TestMethod_LoadCustomer方法进行简单调用并且我在代码中有id字段的malloc时,一切似乎进展顺利,但我的调用代码没有获得更新的id字段。如果我删除malloc调用,我会收到访问冲突。我认为违规是由于id字段将被放入只读存储器而不能直接覆盖。
如何对此进行编码,以便调用应用程序在id字段中接收字符串的更新值?
这是我放在一起的测试应用程序代码,我希望这个代码名称为&#34; 777777&#34;并将其移动到id字段,以便它可以打印到控制台: RunTest.cpp
// RunTest.cpp : Defines the entry point for the console application.
//
#ifdef TestDLL_EXPORTS
#define TestDLL_API __declspec(dllexport)
#else
#define TestDLL_API __declspec(dllimport)
#endif
#include "stdafx.h"
#include <iostream>
#include "TestDLL.h"
using namespace std;
int _tmain()
{
char* id= "";
TestDLL::TestDLL::TestMethod_LoadCustomer("777777", id);
cout << id << "\n";
cout <<"This is a Test\n";
cin >> id;
return 0;
}
感谢您花时间看看我的问题!
答案 0 :(得分:1)
您需要将第二个参数类型更改为char *&id
;当您在id = ...
内TestMethod_LoadCustomer
进行id
时,您只会更改id
的本地版本,而不是外部的&
变量。
在参数中添加id
会使char
引用id
指针,这意味着来自_tmain
的{{1}}将通过引用传递,并且你的代码会起作用。
答案 1 :(得分:0)
您正在修改DLL中指针的值。由于指针id
未作为对指针char *&id
的引用传递,因此对指针值的更改不会反映在TestMethod_LoadCustomer函数的范围之外。我还认为在一个dll中分配内存以跨模块使用是一个坏主意,因为那时你必须确保你的程序和dll都使用相同的C ++运行时编译。更安全的方法是将已分配的缓冲区传递给函数,并让调用程序处理内存管理。
看看here,了解为什么你应该在调用代码中保留资源的所有权。
答案 2 :(得分:0)
您的代码中存在一些问题。 一个小问题是你正在混合C和C ++代码,它可以工作,但可能会混淆理解。 即:您使用std类/对象,但使用c字符串函数(strcpy)和malloc函数。
当您使用 id 参数调用函数时,它会传递指针,指向一个常量值。
:在主函数中,id的值(即它指向的地址)是0x123。 但是,在DLL函数内部为id分配内存,所以现在该函数内的 id 指向不同的地址(即:0x456)
然后,当您的程序返回主函数 id 时仍然指向旧地址,因为函数内部的更改不会反映在外部(因为您更改为其中的位置&#39) ; s指的不是值。)
为了让它按预期工作,您需要确保主要功能 id 中的功能都指向同一个地址,并确保您要更改的位置价值。
为了达到这个目的,你可以使用,即指针指针或指针作为id,然后你可以分配值和复制。
您的代码的丑陋(但功能)版本将是:
namespace TestDLL{
extern "C" int __declspec(dllexport) __stdcall TestDLL::TestMethod_LoadCustomer(const char* name, char* id)
{(char* name, char** id) {
std::string test(name);
if (test.size() <= 8) {
*id = (char*)malloc(strlen(name)+1);
strcpy(*id, name); // name contains customer id
} else {
id[0] = 0; // Customer not found
}
return 0;
}
然后你可以调用传递指针的地址:
int _tmain()
{
char* id= "";
TestDLL::TestDLL::TestMethod_LoadCustomer("777777", &id);
cout << id << "\n";
cout <<"This is a Test\n";
cin >> id;
return 0;
}
但我强烈建议您将代码更改为C或C ++,而不是两者,并且不要忘记_tmain拥有id指针,因此当您不需要时需要释放内存了。