当在线上接收数据并将其发送到上层应用程序时,通常以C风格,我们有一个结构,例如带有void *:
Microsoft Forms 2.0 Object Library
稍后在代码中,在错误检查和mallocating之后,......,我们可以做一些事情:
Option Explicit
Dim DObj
Sub TestClipboard()
Dim ClipData
VerifyArchitecture
If Not InitClipboardObject Then
Terminate "Unable to initialize the clipboard object"
ElseIf Not ClipboardPaste(ClipData) Then
Terminate "Unable to retrieve the clipboard data"
End If
' The message box will have the current clipboard text (if any exist)
MsgBox "The clipboard contains the following text:" & _
vbCrLf & vbCrLf & ClipData
ClipData = "Text we put in the clipboard"
' However, this function will not succeed.
If Not ClipboardCopy(ClipData) Then Terminate "Unable to put data into the clipboard"
End Sub
Function InitClipboardObject()
On Error Resume Next
' If the code is run in VBA, the following reference library
' can be used as an alternative to late binding:
' Microsoft Forms 2.0 Object Library
' Note: The reference library will not show up on the
' list unless a userform has already been added in Excel.
' If not, browse for the FM20.DLL file
Set DObj = GetObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
InitClipboardObject = Err = 0
End Function
' Put data in the clipboard similar to pressing Ctrl + C
Function ClipboardCopy(ByVal Data)
On Error Resume Next
DObj.SetText Data
' This line of code will throw the following error
' Error Number: -2147221008 (800401F0)
' Description: DataObject:PutInClipboard CoInitialize has not been called.
' However, it works perfectly in VBA
DObj.PutInClipboard
ClipboardCopy = Err = 0
End Function
' Retrieve data from the clipboard similar to pressing Ctrl + V
Function ClipboardPaste(ByRef Data)
On Error Resume Next
DObj.GetFromClipboard
Data = DObj.GetText(1)
ClipboardPaste = Err = 0
End Function
' This sub will re-load the script using the 32 bit host
' if it is loaded on the 64 bit version. This is necessary
' since the clipboard object is 32 bit.
Sub VerifyArchitecture()
' The code in this sub is a modified version of Vozzie's answer
' and I do not take credit for the idea:
' https://stackoverflow.com/a/15320768/2734431
Dim Arch, Arg, Args, Cmd, ExeFullName, ExeShortName
Dim Path32, Path64, ProcEnv, q, Reload, ScriptName
Dim WinDir, WShell
q = Chr(34)
Reload = False
ExeFullName = WScript.FullName
ScriptName = WScript.ScriptFullName
ExeShortName = Mid(ExeFullName, InStrRev(ExeFullName, "\") + 1)
Set WShell = CreateObject("WScript.Shell")
Set ProcEnv = WShell.Environment("Process")
WinDir = ProcEnv("windir") & "\"
Path32 = WinDir & "SysWOW64\"
Path64 = WinDir & "System32\"
Arch = ProcEnv("PROCESSOR_ARCHITECTURE")
For Each Arg In WScript.Arguments
Args = " " & q & Arg & q
Next
Cmd = q & Path32 & ExeShortName & q & " " & q & ScriptName & q & Args
If InStr(LCase(ExeFullName), LCase(Path64)) <> 0 And Arch = "AMD64" Then
Reload = True
WShell.Run Cmd
End If
Set WShell = Nothing
Set ProcEnv = Nothing
If Reload Then Terminate ""
End Sub
' This sub is designed to clear any global variables, optionally
' display an error message, and stop the script
Sub Terminate(ByVal ErrMsg)
Dim ErrNbr
Set DObj = Nothing
If ErrMsg <> "" Then
ErrNbr = "Error"
If Err <> 0 Then
ErrNbr = ErrNbr & " " & Err & " (" & Hex(Err) & ")"
ErrMsg = ErrMsg & vbCrLf & vbCrLf
ErrMsg = ErrMsg & "Code Error: " & Err.Description
End If
' &H10 = vbCritical
MsgBox ErrMsg, &H10, ErrNbr
End If
WScript.Quit
End Sub
在C ++中,尝试使用unique_ptr在以下代码段中失败:
struct SData{
//... len, size, version, msg type, ...
void* payload;
}
但是如你所知,这将导致:
if(msgType == type1){
struct SType1* ptr = (struct SType1*) SData->payload;
}
有没有办法使用智能指针来处理这个?
我找到的一个解决方案是: Should std::unique_ptr<void> be permitted
这需要创建自定义删除器:
struct SData{
// .. len, size, version, msg type, ...
std::unique_ptr<void> payload;
}
使用
error: static assertion failed: can't delete pointer to incomplete type
这将需要更多的额外代码(与简单的不安全C风格相比),因为对于每种类型的有效负载,都必须添加一些逻辑。
答案 0 :(得分:1)
这将需要更多的额外代码(与简单的不安全C风格相比),因为对于每种类型的有效负载,都必须添加一些逻辑。
额外的复杂性只是调用添加的析构函数。您可以使用函数指针而不是std::function
,因为不应该使用闭包状态。
如果您不想要析构函数,只想将RAII添加到C语言中,那么请使用自定义删除工具,它只需operator delete
或std::free
。