c++ dll 中函数原型   
long  AVSS_SetActiveDecoder ( HWND hwnd , LPCTSTR url ,LPCTSTR options , char * codecType
                             LONG handleID, LONG paramID , VARIANT paramValue )其中 paramValue.vt = VT_LPSTR  paramValue.pcVAL 为 LPCTSTR 类型c# 中的调用
[Dllimport(dllpath),Charset=Charset.Ansi,CallingConvention = CallingConvention.Cdecl]
public static Int32 AVSS_SetActiveDecoder (IntPtr hwnd, string url ,string options, string
                            codecType , Int32 handleID, Int32 paramID, object paramValue)
运行VS 程序报错: 值不在预期的范围内 现在可以肯定(IntPtr hwnd, string url ,string options, string codecType , Int32 handleID, Int32 paramID) 这几个参数的赋值是没有问题的  主要是paramValue 的问题我在c#中定义了一个结构体
[StructLayout(LayoutKind.Sequential,Pack = 1 )]
public struct paramValue 
{
```public int vt;   //这里因为VT_LPSTR是VC6底层的数据类型,是固定的整数值30
   public string pcVal;
}
paramValue pv = new paramValue ();
pv.vt = 30;
pv.pcVal = "********";我觉得这么调用应该是没有问题的,搜了不少网页,说“值不在预期范围”还是参数赋值的问题,我看了很多网上说关于VARIANT 和object赋值的帖子,通过结构体赋值应该也是可以的吧 ,本人一直用C# ,对VARIANT 这种类型的C++变量不是很熟悉,向大家请教一下解决问题的办法,很急!先谢过了。c#c++

解决方案 »

  1.   

    [quote=引用
    public struct paramValue 
    {
    ```public int vt;   //这里因为VT_LPSTR是VC6底层的数据类型,是固定的整数值30
       public string pcVal;
    }
    paramValue pv = new paramValue ();
    pv.vt = 30;
    pv.pcVal = "********";
    变体类型Variant,能够在运行期间动态的改变类型。变体类型能支持所有简单的数据类型,如整型、浮点、字符串、布尔型、日期时间、货币及OLE自动化对象等,不能够表达Object Pascal对象。!
      

  2.   

    http://www.cnblogs.com/chuncn/archive/2011/12/20/2294096.html
    但在这个网上查的结果,调用变体类型参数转换只能是object类型啊,你有成功调用含variant类型dll的实例吗?
      

  3.   

    variant 虽然是变体类型,但也不是瞎变的,你这个结构体对象传入,运行时会出错的!
      

  4.   

    paramValue pv = new paramValue (); 结构体对象 声明就行了,不需要new
      

  5.   

    不new的话,怎么给结构体里面的 vt 和 pcVal赋值呢?
      

  6.   

    paramValue pv;就可以了,strut 不需要newVARIANT paramValue封装的时候是什么类型,传入对应的c#类型就可以了啊,难道封装的是自定义类型?
      

  7.   

    是在VS2010里面直接调用C++写的DLL,DLL里面函数的参数有的是固定死的,有的是在VS程序里面赋值,VARIANT paramValue封装的时候就封装成了VARIANT 变体类型的,到VS里面这个类型需要和C#对应的类型(OBJECT)匹配以便赋值啊,现在问题是我自己定义的结构体传值过去报错~
      

  8.   

     VT_LPSTR不是标准的,缺省Marshal方式是 VT_BSTR,你改下c++这端吧。
      

  9.   


    VT_LPSTR不常见。不改的话,C#方面就要自己传VARIANT结构。另,你的paramValue定义有误。private void button1_Click(object sender, EventArgs e)
    {
        // Marshal帮你传VARIANT,但字符串将作为BSTR
        Show(this.Handle, "hello world");
        Show(this.Handle, 1234);
        Show(this.Handle, new object[] { "nihao", 5678, "abcd" });
    }
    private void button2_Click(object sender, EventArgs e)
    {
        // 自己传VARIANT结构
        Variant v = new Variant()
        {
            vt = 30,   //VT_LPSTR
            byref = Marshal.StringToHGlobalAnsi("Bonjour"),
        };
        Show(this.Handle, v);
        Marshal.FreeHGlobal(v.byref);
    }
            
    [DllImport("MyDll.dll", CallingConvention=CallingConvention.Cdecl)]
    extern static void Show(IntPtr hWnd, object variant);[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
    extern static void Show(IntPtr hWnd, Variant variant);[StructLayout(LayoutKind.Sequential)]
    struct Variant
    {
        public short vt;
        private short reserved1, reserved2, reserved3;
        public IntPtr byref;
    }C++测试代码:// mydll.cpp
    #include "stdafx.h"
    #include <atlstr.h>
    #include <Windows.h>CStringW GetString(const VARIANT& v)
    {
        CStringW result;
        if (v.vt == VT_BSTR)
        {
            result = v.bstrVal;
        }
        else if(v.vt == VT_LPSTR)
        {
            result = (LPSTR)v.byref;
        }
        else if (v.vt == VT_I4)
        {
            result.Format(L"%d", v.intVal);
        }
        else if (v.vt == VT_ARRAY | VT_VARIANT && v.parray->cDims == 1)
        {
            VARIANT* pArray = (VARIANT*)v.parray->pvData;
            int count = v.parray->rgsabound[0].cElements;
            for(int i=0; i < count; i++)
            {
                result.AppendFormat(L"%s ", GetString(*(pArray + i)));
            }
        }
        return result;
    }extern "C" _declspec(dllexport) void Show(HWND hWnd, VARIANT v)
    {
        MessageBoxW(hWnd, GetString(v), L"From C++ dll", MB_OK);
    }
      

  10.   

    .net 直接提供了转换为variant的函数
    Marshal.GetNativeVariantForObject 
      

  11.   

    paramValue pv = new paramValue (); 结构体对象 声明一下就差不多吧,应该不需要用new了
      

  12.   

    C++里面的调用是这样的TRACE(paramValue.pcVal);
    tempRet = pcurrentPlugin->fncSetParam(connectRet,paramID,paramValue);就这两句用到了,没什么特殊的
      

  13.   

    版主,这个是VS2012的吧,.NET 4.5 我还是VS2010在4阶段呢~
      

  14.   

    其实无所谓标准,只是个俗称。
    因为最早variant是vba(ole/com的前身)中的类型,只有vt_bstr,这个特性也保留到ole/com作为传递字符串的类型。bstr就是前面是4字节的字符串长度,后面跟unicode的字符串,没有\0结束符,这跟c++中的lpstr的不一样的地方。
      

  15.   

    TRACE(paramValue.pcVal);
    这个参数在c++如何构造的