[英]Marshaling C++ void* parameters
我正在嘗試編組 Adobe XMPToolKitSDK XMPFiles.dll 和 XMPCore.dll。 這是我第一次做這樣的事情,對於不包含“void *”類型參數的方法來說,事情似乎運行良好。 請幫助我使用下面的代碼。 謝謝!
C++ function 是:
void
WXMPMeta_GetProperty_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
void * propValue,
XMP_OptionBits * options,
SetClientStringProc SetClientString,
WXMP_Result * wResult ) /* const */
{
XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetProperty_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
XMP_StringPtr valuePtr = 0;
XMP_StringLen valueSize = 0;
XMP_OptionBits voidOptionBits = 0;
if ( options == 0 ) options = &voidOptionBits;
bool found = thiz.GetProperty ( schemaNS, propName, &valuePtr, &valueSize, options );
wResult->int32Result = found;
if ( found && (propValue != 0) ) (*SetClientString) ( propValue, valuePtr, valueSize );
XMP_EXIT
}
我創建了一個 Wrapper 方法和一個 Delegate,如下所示:
//typedef void (* SetClientStringProc) (void* clientPtr, XMP_StringPtr valuePtr, UInt32 XMP_StringLen);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void SetClientStringProcDelegate(ref IntPtr clientPtr, string valuePtr, ulong valueLen);
// 20 1F 00002E30 WXMPMeta_GetProperty_1 = WXMPMeta_GetProperty_1
[DllImport(".\\XMPToolKitSDK\\XMPCore.dll")]
public static extern void WXMPMeta_GetProperty_1(
IntPtr xmpObjRef,
string schemaNS,
string propName,
ref IntPtr propValue,
ref ulong options,
SetClientStringProcDelegate SetClientString,
ref WXMP_Result wResult
); /* const */
而且,為了讓我的生活更輕松,我還創建了一個 static class 包含以下方法:
public static WXMP_Result getProperty(IntPtr xmpObjRef, string schemaNS, string propName, ref IntPtr propValue, ref ulong options, SetClientStringProcDelegate SetClientString)
{
WXMP_Result wResult = new WXMP_Result();
XMPMetaWrapper.WXMPMeta_GetProperty_1(xmpObjRef, schemaNS, propName, ref propValue, ref options, SetClientString, ref wResult);
return wResult;
}
在我的測試代碼中,我這樣做:
string schemaNS = kXMP_NS_SKYVIEW;
string propName = "CustomField40";
IntPtr propValue = new IntPtr();
options = 0;
SetClientStringProcDelegate setClientStringDelegate = new SetClientStringProcDelegate(mySetClientString);
WXMP_Result getPropertyResult = XMPMeta.getProperty(xmpMetaObjRef, schemaNS, propName, ref propValue, ref options, setClientStringDelegate);
Console.WriteLine("getPropertyResult: " + propValue);
// Callback Methods
public static void mySetClientString(ref IntPtr clientPtr, string valuePtr, ulong valueLen)
{
Console.WriteLine("mySetClientString|clientPtr: " + clientPtr + "|valuePtr: " + valuePtr + "|valueLen: " + valueLen);
}
當我運行我的 testCode 時,會調用 Callback function,結果是:
XMP Obtido com sucesso: 472446411633
doesPropertyExistResult: 1
mySetClientString|clientPtr: 0|valuePtr: Objects detected | 4 Faces detected and 2 Faces identified|valueLen: 58
getPropertyResult: 0
如您所見,屬性值是由回調 function“mySetClientString”檢索和打印的,作為 valuePtr。 但是,由於某種原因,我無法弄清楚,通過引用“propValue”傳遞的變量沒有返回任何內容。 我是否正確地將“void *”編組為 IntPtr?
請指教! 提前致謝!
感謝大家的評論,特別是@IS4 指出我所缺少的。 原來的 C++ function 接收到一個 ref void (void*) ,然后通過 ref 傳遞給回調 function,它應該設置在這個參數中返回的最終值。
有一個棘手的問題是獲取原始 function 返回的字符串並將其作為 IntPtr 返回。 我不明白為什么 Adobe 會這樣做,但解決方案是將字符串編組到回調 function 內的 IntPtr 中,然后在 function 運行后將其編組回來。 我已經使用此代碼編輯了原始問題,以便任何尋找此代碼的人都能獲得最終解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.