标签: safearray

如何将本地CComSafeArray返回到LPSAFEARRAY输出参数?

我有一个COM函数应该通过LPSAFEARRAY*out参数返回一个SafeArray .该函数使用ATL的CComSafeArray模板类创建SafeArray .我的天真实现用于CComSafeArray<T>::Detach()将所有权从局部变量移动到输出参数:

void foo(LPSAFEARRAY* psa)
{
    CComSafeArray<VARIANT> ret;
    ret.Add(CComVariant(42));
    *psa = ret.Detach();
}

int main()
{
    CComSafeArray<VARIANT> sa;
    foo(sa.GetSafeArrayPtr());

    std::cout << sa[0].lVal << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

问题是CComSafeArray::Detach()执行一个Unlock操作,以便当SafeArray的新所有者(sa在这种情况下为main )被销毁时,锁定不为零并且Destroy无法解锁SafeArray E_UNEXPECTED(这导致内存泄漏,因为SafeArray不是解除分配).

通过COM方法边界将所有权转移到CComSafeArrays的正确方法是什么?


编辑:从单个答案到目前为止似乎错误是在客户端(main)而不是从服务器端(foo),但我发现很难相信这CComSafeArray不是为这个琐碎的用例设计的,必须是一种优雅的方法,可以将COMA方法中的SafeArray转换为CComSafeArray.

c++ com atl safearray

11
推荐指数
2
解决办法
4372
查看次数

如何在C++中创建和初始化双精度SAFEARRAY以传递给C#

我需要从C++调用我的C#方法

最初我的C#方法接受double []类型的参数,但是当从C++调用时它变成了SAFEARRAY

在C++中,我需要从双精度数组中获取数据,并填充SAFEARRAY.我没有找到任何示例代码来执行此操作.

任何帮助表示赞赏

c# c++ safearray visual-c++

11
推荐指数
2
解决办法
3万
查看次数

如何迭代SAFEARRAY**

如何迭代C++ safearray指针指向并访问其元素.

我试图复制发表林生物LIONG解决 http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/022dba14-9abf-4872-9f43-f4fc05bd2602 但奇怪的是,该IDL方法签名出来了

HRESULT __stdcall GetTestStructArray([out] SAFEARRAY ** test_struct_array);
Run Code Online (Sandbox Code Playgroud)

代替

HRESULT __stdcall GetTestStructArray([out] SAFEARRAY(TestStruct)* test_struct_array);
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

提前致谢

c++ com safearray

10
推荐指数
1
解决办法
2万
查看次数

从c ++ DLL和c#发布SAFEARRAY

我有一个c ++函数来获取数据,我从c#调用它.该函数获取一个指向SAFEARRAY的指针并用字符串弹出它(使用SysAllocString)

一切都很好,但程序泄漏了内存.

我做了一点搜索,发现如果我将此属性添加到方法签名:

 [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
 out string[] strServerList
Run Code Online (Sandbox Code Playgroud)

我需要在c ++代码中释放它(它被分配),所以我创建了这个函数

 [DllImport("Native.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "DeallocateExternal")]
 internal static extern void DeallocateExternal(
 [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
 out string[] strServerList);
Run Code Online (Sandbox Code Playgroud)

在我的DLL中我写了这段代码

void DeallocateExternal(SAFEARRAY** psa)
{
    LONG cDims = SafeArrayGetDim(*psa);
    BSTR* pvData = (BSTR*)((*psa)->pvData); 
    for (LONG x = 0; x < cDims; x++)
    {
       SysFreeString(pvData[x]);
    }
    SafeArrayDestroy(*psa); 
}
Run Code Online (Sandbox Code Playgroud)

但我有一个例外:

Tester.exe中发生了未处理的"System.AccessViolationException"类型异常

附加信息:尝试读取或写入受保护的内存.这通常表明其他内存已损坏.

怎么了?

c# c++ memory interop safearray

9
推荐指数
1
解决办法
2918
查看次数

是否可以在SAFEARRAY中编组参数参数

这是我的C#服务器方法:

public void Exec(out int status, string output)
{
     status = 3;
     Console.WriteLine("Exec({0}, ...)", status);

     output = string.Format("Hello from .NET {0}", DateTime.Now);
     Console.WriteLine("Exec(..., {0})", output);         
}
Run Code Online (Sandbox Code Playgroud)

我的C++客户端正在设置并调用此方法.这工作正常,但状态和输出变量似乎不是链接.就好像它们是通过价值而不是通过引用传递的.

这是我的客户端代码:

InitCLR();

LONG index = 0;

LONG i1 = 12; // just some number for testing
BSTR s1 = SysAllocString(L"Hello world");

SAFEARRAY* args = NULL;
CHECK_HRESULT( SafeArrayAllocDescriptor(1, &args) );

args->cbElements = sizeof(VARIANT);
args->rgsabound[0].lLbound = 0;
args->rgsabound[0].cElements = 2;

CHECK_HRESULT( SafeArrayAllocData(args) );   

// byref not working for in/out param   
VARIANT arg1;
VariantInit(&arg1);
V_I4REF(&arg1) = …
Run Code Online (Sandbox Code Playgroud)

.net parameters marshalling safearray

9
推荐指数
1
解决办法
544
查看次数

如何使用SATREARRAY为BSTR的VARIANT显示值

我的工作与功能的COM对象库,它返回一个VARIANT带有SAFEARRAYBSTR秒.如何显示此VARIANT实例的值并将其保存在TStringList?我试着在网上搜索没有明确的答案.

我尝试了以下但没有成功:

Variant V;
String mystr;

VarClear(V);
TVarData(V).VType = varOleStr;
V = ComFunction->GetValues();  //<<<<----- V is empty
mystr = (wchar_t *)(TVarData(V).VString);
Memo1->Lines->Add(mystr);
VarClear(V);
Run Code Online (Sandbox Code Playgroud)

delphi bstr c++builder safearray

8
推荐指数
1
解决办法
5761
查看次数

将自定义类型的Safearray从C++传递到C#

如何使用a Safearray将一组自定义类型(一个只包含属性的类)从C++传递给C#?使用该VT_RECORD类型的方法是正确的吗?

我正在尝试以下方式,但SafeArrayPutElement在尝试填充safearray时返回错误,对类数组的引用以NULL形式获取托管代码.

我在托管世界中有以下内容:

[ComVisible(true)]
public interface IStatistics
{
    double Mean { get; set; } 
    double StdDev { get; set; } 
}

[Serializable]
[ComVisible(true)]
public class Statistics : IStatistics
{
    public Mean { get; set; }
    public double StdDev { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

未管理的世界:

HRESULT hr = CoInitialize(NULL);
...
SAFEARRAY *pEquationsStatistics;

// common dimensions for all arrays
SAFEARRAYBOUND dimensions[1];  
dimensions[0].cElements = 2;   
dimensions[0].lLbound = 0;    

pEquationsStatistics = SafeArrayCreate(VT_RECORD, 1, dimensions);
... …
Run Code Online (Sandbox Code Playgroud)

c# c++ com serialization safearray

6
推荐指数
1
解决办法
3993
查看次数

如何建立一个指向VARIANTs的SAFEARRAY指针?

我正在尝试使用以下方法的COM组件:

HRESULT _stdcall Run(
    [in] SAFEARRAY(BSTR) paramNames,
    [in] SAFEARRAY(VARIANT *) paramValues
    );
Run Code Online (Sandbox Code Playgroud)

如何在C/C++中创建paramValues数组?

c++ com variant safearray

6
推荐指数
2
解决办法
1万
查看次数

GUID的COM SAFEARRAY从C++返回到C#

我目前遇到一个问题,需要将SAFEARRAY(GUID)作为返回值从C++传递给C#.

目前,C#端正在使用从Tlbimp.exe(类型库导入程序)生成的Interop dll.

IDL是:

HRESULT GetGuids(
    [out]SAFEARRAY(GUID)* guids);
Run Code Online (Sandbox Code Playgroud)

我也试过[out,retval]

功能签名是:

HRESULT
WINAPI
MyClass::GetGuids(SAFEARRAY** guids)
Run Code Online (Sandbox Code Playgroud)

如果我使用SafeArrayCreate()SafeArrayCreateVector():

SAFEARRAY* psa
psa = SafeArrayCreate(VT_CLSID, 1, rgsabound);
Run Code Online (Sandbox Code Playgroud)

我得到一个NULL SAFEARRAY指针,它应该指示E_OUTOFMEMORY哪个是不正确的.

我发现的VT_CLSID只是Ole属性集而不是SAFEARRAY:http: //poi.apache.org/apidocs/org/apache/poi/hpsf/Variant.html它表明CLSID是

我还尝试了使用以下方法构建安全数组的替代方法: SafeArrayAllocDescriptor()SafeArrayAllocData().

hResult = SafeArrayAllocDescriptor(1, guids)
hResult = SafeArrayAllocData(*guids);
Run Code Online (Sandbox Code Playgroud)

这让我创建了数组,但是当SafeArrayPutElement()我用它填充它时,我得到一个0x80070057的HRESULT(参数不正确).这可能是因为它也需要VT_CLSID参数

我可以手动填充它 SafeArrayAccessData()

GUID* pData = NULL;
hResult = SafeArrayAccessData(*guids, (void**)&pData);
Run Code Online (Sandbox Code Playgroud)

但我从C#端得到一个错误:"该值不在预期的范围内"

我不确定如何通过retval或out参数完成将SAFEARRAY(GUID)返回到C#的所需功能.

它似乎应该很简单 - IDL中有很多区域我已经在没有任何UDT或编组的情况下传递GUID.一切正常,直到我需要在SAFEARRAY传递它们.

任何帮助表示赞赏,在此先感谢

c# c++ com guid safearray

6
推荐指数
1
解决办法
1985
查看次数

如何通过IDispatch将SAFEARRAY传递给COM对象?

我试图调用COM对象的方法,其中一个记录的参数是"字节数组 ".实际声明取决于您正在查看的每种语言文档:

我正在使用的对象也可以使用COM访问.该对象提供了一个早期绑定接口ICryptoTransform,它将该方法声明为using SAFEARRAY.

类型库:

com winapi variant safearray

6
推荐指数
1
解决办法
6399
查看次数