为c/c++代码编写ctypes包装器的正确方法

Correct way of writing a ctypes wrapper for c/c++ code

本文关键字:包装 方法 ctypes c++ 代码      更新时间:2023-10-16

感谢您花时间阅读,我希望您能回答:)

我将首先解释我所做的研究等等,试图纠正这个问题,只是为了提供一些背景。此外,我认为自己有相当强的python知识。

我查阅了DLL/neneneba API文档试图理解,我也花了一天时间复习c++,试图理解我的问题:

我有一个C++(我很确定)程序,我想在python中实现它。我觉得我知道如何尝试转换(ahem),除了一部分我无法理解(我知道这是一个开始,但我相信其他部分应该到位)

#import "pstorec.dll" no_namespace
void foo()
{
IPStorePtr PStore; 
IEnumPStoreTypesPtr EnumPStoreTypes;

我一辈子都无法理解第5/6行发生了什么,也无法理解如何在python/c中实现这一点类型。

我试着把它们称为"pstorec.dll"的函数,但当然,这不起作用,有人能解释一下吗。我已经通读了http://starship.python.net/crew/theller/ctypes/tutorial.html我个人找不到解决办法。所以我很清楚我误解了什么。

谢谢,提前。

p.s,我知道第一个单词(variable?)想要成为一个指针,但除此之外,我迷失了方向。希望有人能理解我的要求:)

以下完整代码:

#import "pstorec.dll" no_namespace
void ListIEProtectedStorageSecrets()
{
IPStorePtr PStore; 
IEnumPStoreTypesPtr EnumPStoreTypes;
GUID TypeGUID;
char strSiteUrl[1024]; 
char strSiteCredentials[1024];
char szItemGUID[1024];
char strUsername[1024];
char strPassword[1024];
HRESULT hRes = PStoreCreateInstance(&PStore, 0, 0, 0); 
hRes = PStore->EnumTypes(0, 0, &EnumPStoreTypes);

 while( EnumPStoreTypes->raw_Next(1, &TypeGUID, 0) == S_OK )
 { 
   sprintf_s(szItemGUID, 1024, "%x", TypeGUID);
   IEnumPStoreTypesPtr EnumSubTypes;
   hRes = PStore->EnumSubtypes(0, &TypeGUID, 0, &EnumSubTypes);
   GUID subTypeGUID;
   while(EnumSubTypes->raw_Next(1,&subTypeGUID,0) == S_OK)
   {
     IEnumPStoreItemsPtr spEnumItems;
     HRESULT hRes = PStore->EnumItems(0, &TypeGUID, &subTypeGUID, 0, &spEnumItems);
 //Now enumerate through each of the stored entries.....
 LPWSTR strWebsite;
 while( spEnumItems->raw_Next(1, &strWebsite, 0) == S_OK)
 { 
    sprintf_s(strSiteUrl, 1024, "%ws", siteName); 
    unsigned long psDataLen = 0;
    unsigned char *psData = NULL;
    char *sptr;
    _PST_PROMPTINFO *pstiinfo = NULL;
   //read the credentails for this website entry
   hRes = PStore->ReadItem(0, &TypeGUID, &subTypeGUID, siteName, &psDataLen, &psData, pstiinfo, 0);
   if( lstrlen((char *)psData)<(psDataLen-1) )
   {
     int i=0;
     for(int m=0; m<psDataLen; m+=2)
     {
       if(psData[m]==0)
         strSiteCredentials[i]=',';
       else
         strSiteCredentials[i]=psData[m];
       i++;
     }
     strSiteCredentials[i-1]=0; 
   }
   else 
   { 
      sprintf_s(strSiteCredentials, 1024, "%s", psData); 
   } 
   //Now decode the username & password from strSiteCredentials for different types
   //5e7e8100 - IE:HTTP basic authentication based passwords
   //username and passwords are seperated by ':'
   if(lstrcmp(szItemGUID, "5e7e8100") ==0 ) 
   { 
     strPassword[0]=0;
     sptr = strstr(strSiteCredentials, ":");
     if( sptr != NULL )
     {
       strcpy_s(strPassword, 1024, sptr+1);
       *sptr = 0;
       strcpy_s(strUsername, 1024, strSiteCredentials); 
     }
     printf("n website = %S, username = %s, password = %s", strSiteUrl, strUsername, strPassword);
   }

   //e161255a - IE autocomplete passwords
   if(lstrcmp(szItemGUID,"e161255a")==0)
   {
     if(strstr(strSiteUrl, "StringIndex" ) == 0 )
     {
       if(strstr(strSiteUrl,":String")!=0) 
         *strstr(strSiteUrl,":String")=0; 
       lstrcpyn(strPassword,strSiteUrl,8); 
       if( !( (strstr(strPassword,"http:/")==0)&&(strstr(strPassword,"https:/")==0) ) )
       {
           //username & passwords are seperated by ','
           strPassword[0]=0;
           sptr = strstr(strSiteCredentials,",");
           if( sptr != NULL )
           {
              strcpy_s(strPassword, 1024, sptr+1);
              *sptr = 0;
              strcpy_s(strUsername, 1024, strSiteCredentials); 
           }
           printf("n website = %s, username = %s, password = %s", strSiteUrl, strUsername, strPassword);
        }
      }
    } //end of autocomplete if
  } //inner while loop
 } //middle while loop
   } //top while loop
} //end of function

缩进变得很有趣(是的,我的错:)),但我不认为它会影响问题,如果你能忽略这一点的话:)

看看你的完整代码,这绝对是C++,它利用了COM(组件对象模型),更重要的是,这个库似乎对你隐藏了大部分COM的"丑陋"。话虽如此,我不确定你是否会知道IPStore真的是。

请参阅此参考资料以了解COM。特别是,请参阅图4。我怀疑IPStorePtr是一个接口指针,它允许客户端代码与客户端对话。

我还怀疑PStoreCreateInstanceCoCreateInstanceQueryInterface的包装器(两者都是普通COM API的一部分)。所以在这一行代码中:

HRESULT hRes = PStoreCreateInstance(&PStore, 0, 0, 0); 

hRes是PStoreCreateInstance函数的返回状态(您应该始终检查)。另外,请注意,我们将传递PStore的地址(&PStore)作为第一个参数。如果此函数成功,您将有一个指向COM对象上接口的指针。

在这行代码中:

hRes = PStore->EnumTypes(0, 0, &EnumPStoreTypes);

我们使用指向COM对象的指针来调用在对象CCD_ 6中定义的函数。