#2
ThinkerHua2022-06-22 20:51
|
char *SectionSteelAW(char const *RawText, unsigned const CtrlCode);
返回值为char *类型。
同时我还用C编写了一个Demo程序,调用这个DLL,是能够正常执行的。
(这个DLL项目及Demo所有源码我已上传到github上,地址为:https://)
但是在程序里,始终不能正常执行,具体表现为:
1、返回值始终是nothing
2、执行此函数后,实参RawText的值会被改变
3、执行几次之后,报错:System.AccessViolationException:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
(这个程序所有源码我也已上传到github上,地址为:https://,见分支V2)
请问如何正确调用此函数?
另请问,正确调用此函数后,得到的返回值字符串不需要使用时,如何正确释放内存空间?
(函数内部是通过动态分配内存提供的返回值,由于我的Demo程序是C编写的,可以用free(Resault)来释放。但是中该如何做?)
恳请前辈们不吝赐教!!!
SectionSteelAW函数由于底层实现代码较多,不便全部贴出,仅贴出最终实现代码:
程序代码:
#include "dll.h"
#include "calculation.h"
#include <string.h>
#include <windows.h>
DLLIMPORT char *SectionSteelAW(char const *RawText, unsigned const CtrlCode) {
char *FormatedText = NULL;
char *SecSteType = NULL;
char *Resault = NULL;
void *obj = NULL;
if (formatting(RawText, &FormatedText) == 0)
return NULL;
SecSteType = getSecSteType(FormatedText);
if (SecSteType == NULL)
return NULL;
obj = NewObj(SecSteType);
if (obj == NULL)
return NULL;
if (SetData(obj, SecSteType, FormatedText) == 0) {
FreeObj(&obj, SecSteType);
return NULL;
}
Resault = getResault(obj, SecSteType, CtrlCode);
FreeObj(&obj, SecSteType), obj = NULL;
free(FormatedText), FormatedText = NULL;
//SecSteType来自const字符串数组,不需要释放,只需赋值NULL
SecSteType = NULL;
return Resault;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) {
switch(fdwReason) {
case DLL_PROCESS_ATTACH: {
break;
}
case DLL_PROCESS_DETACH: {
break;
}
case DLL_THREAD_ATTACH: {
break;
}
case DLL_THREAD_DETACH: {
break;
}
}
/* Return TRUE on success, FALSE on failure */
return TRUE;
}
C语言Demo程序的具体代码如下:
程序代码:
#include <windows.h>
#include <stdio.h>
/*
#define TYPE_AREA 1
#define TYPE_EXCLUDE_TOPSURFACE 2
#define TYPE_WEIGHT 4
#define METHOD_ROUGHLY 8
#define METHOD_PRECISELY 16
#define METHOD_LOOKUP 32
DLLIMPORT char *SectionSteelAW(char const *RawText, unsigned const CtrlCode);
*/
typedef char *(*p_SectionSteelAW)(char const *RawText, unsigned const CtrlCode);
int main (int argc, char *argv[]) {
HMODULE module = NULL;
p_SectionSteelAW SSAW = NULL;
char *resault = NULL;
char RawText[64] = {'\0'};
unsigned ctrlcode = 0;
module = LoadLibraryA("SectionSteelAW.dll");
if (module == NULL) {
MessageBox(0,"Cannot start this program because of missing \"SectionSteelAW.dll\" file!\n","Error",MB_ICONERROR);
return 0;
}
SSAW = (char *(*)(char const *, unsigned const))GetProcAddress(module, "SectionSteelAW");
if (SSAW == NULL)
goto clean;
while (scanf("%s %u", RawText, &ctrlcode) != EOF) {
resault = SSAW(RawText, ctrlcode);
if (resault != NULL)
printf("%s\n", resault);
free(resault);
resault = NULL;
}
clean:
FreeLibrary(module);
return 0;
}
测试结果是能够正常工作的
输入:H244*175 19
输出:0.244*2+0.175*3-0.007*2
输入:D210*5 33
输出:PI()*0.21
输入:PL500*600*12-PLT120*100*12-PLD150*12 36
输出:(0.5*0.6-0.12*0.5*0.1-PI()*0.075^2)*0.012*7850
这里想插入截图的,不知道怎么插入
程序中的具体应用代码如下(全局变量的赋值修改对此问题没有影响,所以相关代码就不贴出来了):
程序代码:
Module SectionSteelAW
Public Const _TESTFLAG = 0 '测试代码控制符
Public Const TYPE_AREA = 1 '计算类型:面积
Public Const TYPE_EXCLUDE_TOPSURFACE = 2 '计算类型:面积子项,扣除顶面
Public Const TYPE_WEIGHT = 4 '计算类型:重量
Public Const METHOD_ROUGHLY = 8 '计算模式:粗略
Public Const METHOD_PRECISELY = 16 '计算模式:精细
Public Const METHOD_LOOKUPINTABLE = 32 '计算模式:查表
Public CTRLCODE As Integer = 0 '控制码
Public Offset_Rows As Integer = 0 '目标行偏移参数
Public Offset_Columns As Integer = 1 '目标列偏移参数
Public Overwrite As Integer = 0 '目标已有数据是否覆盖参数
Public Declare Function SectionSteelAW Lib "SectionSteelAW.dll" (ByVal RawText As String, ByVal CtrlCode As UInteger) As String
Public Sub Generate()
Dim xlApp As Object = Nothing 'Excel对象
Dim xlWorkbook As Object = Nothing '工作薄对象
'Dim xlSheet As Object = Nothing '工作表对象
Dim xlRange As Object = Nothing '单元格区域
Dim xlCell As Object = Nothing '单元格
Dim sRawText As String = Nothing
Dim sResault As String = Nothing
Dim starttime As Date
Dim endtime As Date
'获取Excel程序、工作薄、工作表、选定区域
On Error Resume Next
xlApp = GetObject(, "Excel.Application")
If Err.Number <> 0 Then
Err.Clear()
MsgBox("Please open an Excel application first!", vbOKOnly + vbExclamation, "Waring")
Exit Sub
End If
xlWorkbook = xlApp.ActiveWorkbook
If xlWorkbook Is Nothing Then
MsgBox("Please open an Workbook first!", vbOKOnly + vbExclamation, "Waring")
Exit Sub
End If
xlRange = xlApp.Selection
On Error GoTo 0
If _TESTFLAG Then starttime = System.DateTime.Now
'xlApp.screenupdating = False
For Each xlCell In xlRange
'不覆写且目标不为空时直接跳过
If (Overwrite = 0) And (xlCell.offset(Offset_Rows, Offset_Columns).value IsNot Nothing) Then Continue For
sRawText = xlCell.Value
sResault = SectionSteelAW(sRawText, CTRLCODE)
'输出到Excel
If sResault IsNot Nothing Then
xlCell.offset(Offset_Rows, Offset_Columns).Value = "=" & sResault
'赋值为Nothing是否能正确释放???
sResault = Nothing
Else
xlCell.offset(Offset_Rows, Offset_Columns).Value = Nothing
End If
Next
'xlApp.screenupdating = True
If _TESTFLAG Then endtime = System.DateTime.Now : MsgBox("执行持续时间:" & (endtime - starttime).ToString)
'释放对象内存
xlCell = Nothing : xlRange = Nothing : xlWorkbook = Nothing : xlApp = Nothing
End Sub
End Module
[此贴子已经被作者于2022-6-21 20:23编辑过]