本帖最后由 zero112 于 2010-08-11 13:55:12 编辑

解决方案 »

  1.   

    这个问题跟我出现的问题一样,我代码是这样写的:每次运行到Handle = QLIB_ConnectServer_LogicalPort(com),都会提示“实时错误49,DLL调用约定错误”。同是天涯沦落人啊,还是试了一天了,还是没有解决,也出来寻求帮助了
    Dim Handle As Variant
    Dim result As Byte
    Private Declare Function QLIB_FTM_BT_Enable_Bluetooth Lib "QMSL_MSVC6R.dll" (ByVal Handle As Variant) As Byte  Private Declare Function QLIB_ConnectServer_LogicalPort Lib "QMSL_MSVC6R.dll" (ByVal iLogicalPort As Long) As Variant  
    com = Val(Trim(AT_COM))
    Handle = QLIB_ConnectServer_LogicalPort(com)   
    result = QLIB_FTM_BT_Enable_Bluetooth(Handle)
      

  2.   

    看一下这个贴吧,可能有帮助:
    http://topic.csdn.net/t/20020925/16/1052521.html
      

  3.   

    感谢,我看了下2楼给的链接,现在问题就关注于SEN_ReadDSPData此函数
    目的是要看到成功或失败的返回值,从中截取参数获取过程值,但是现在不知道VB语句怎么写才能成功
      

  4.   

    并不是只要是DLL,VB就能调用的。
    DLL 有两种,一种是C专用的DLL,另一种是通用DLL。VB只能调用通用DLL。如果在C里面这样申明 double SEN_WaveToTemp(double fWave, int iChannel, int iSensor);
    生成的就是C专用的DLL,只能被C语言调用。如果其它语言调用这样的DLL就是“DLL调用约定错误”通用DLL必须这样申明:
    double WINAPI SEN_WaveToTemp(double fWave, int iChannel, int iSensor);当然,尽管上述声明是可用的但是建议用WINAPI 声明的函数一律返回 int 值,指示函数是否执行成功。如果需要返回其它类型的值请在参数中返回。
      

  5.   

    如果产生“DLL调用约定错误”,原因就只可能是DLL是C专用的这一个原因,没有其它原因也会产生这个错误了吗?比如参数传递错误等是否也会产生DLL调用约定错误
      

  6.   

    供 VB 调用的函数必须是 stdcall 的,4楼说的 WINAPI 就是 define 的别名。
    我看你前面几个函数调用都成功了,觉得总应该是统一的格式。
    让 VC 程序员检查一下。
      

  7.   


    //在VC中,通过结构体传参,最好使用指针,如:
    int SEN_ReadDSPData(stCHANNEL_LIST *pChannelData)
    {
       //...
    }
    '在VB中申明按地址传递
    Private Declare Function SEN_ReadDSPData Lib "ReadData.dll" (pChannelData As Any) As Long'使用方法大致这样
    Private Type stCHANNEL_LIST
       nChNum As Long '通道号。
       nFreq As Long '该时间内采集的频率。
    End TypePrivate Sub Command7_Click()
       Dim clBuffers() As stCHANNEL_LIST
       Dim rd As Long
       redim clBuffers(10)
       '...
       rd = SEN_ReadDSPData(clBuffers(0))
       Text1.Text = rd
    End Sub
      

  8.   


    因为我没学过VC所以对C申明不理解,他这样写是否用VB调用不了呢,昨天跟对方联系他表示VB没试过,用.NET可以成功但是麻烦一些
      

  9.   


    谢谢,请问是否必须让对方修改VC.DLL里的申明才能执行以上VB申明和调用呢?
    偶按照以上VB语句修改后执行,VB报内存出错,不能用written之类就关闭VB了
    对方说,如果只调用返回函数值应该成功是0,失败非0... 如果要提取过程值,需要截取参数值进行解析,因为首要返回函数就提示失败提示必选参数,所以也不知道提取过程值的语句该怎么写了
      

  10.   

    你可以尝试传递一个内寸句柄过去   Private Declare Function SEN_ReadDSPData Lib "ReadData.dll" (pChannelData As Long) As Long
       Dim Buffer As Long
       Dim rd As Long
       Buffer = GlobalAlloc(GMEM_ZEROINIT, 8*11)
       rd = SEN_ReadDSPData(Buffer)
       'Buffer就是内存句柄
       ...
       GlobalFree Buffer
      

  11.   

    还有,通常API函数在VC中定义成静态的比较合适,如:int _stdcall SEN_ReadDSPData(stCHANNEL_LIST *pChannelData)
    {
       //...
    }
      

  12.   

    感谢,但是按照以上执行提示GlobalAlloc子程序或函数未定义我现在有点迷惑,其他函数同样语句TEXT1.TEXT= XXX都有返回值
    执行TEXT1.TEXT=SEN_ReadDSPData,却提示必选参数
    是否Private Declare Function SEN_ReadDSPData Lib "ReadData.dll" _
             (ByVal stCHANNEL_LIST As Long, _
              ByVal pChannelData As Long, _
              ByVal nSensorCount As Long, _
              ByVal fWaveLengthVec As Long, _
              ByVal fPowerDBVec As Long, _
              ByVal nChNum As Long, _
              ByVal nFreq As Long, _
              ByVal tSensorListVec As Long) As Long
    这个申明写错了呢?
    还是因为 std::vector<float> fWaveLengthVec; 该通道的传感器波长序列。
    std::vector<float> fPowerDBVec; 该通道的传感器功率序列。
             std::vector<stCHANNEL_SENSOR_LIST> tSensorListVec; 传感器序列。
    这个几个结构体参数VB完全不能调用呢?因为确定这点以后我可以找VC程序员商量,现在心里没底不确定,请大家解惑,谢谢。
      

  13.   

    你应该先弄清楚VC函数的原型,然后再声明函数,如果你不知道该如何声明,你可以把VC的函数原型发上来,我帮你看看
      

  14.   

    DLL调用约定错误函数原型,你在VB6中的申明不符合函数原型的描述。
      

  15.   

    请问函数原型是指VC DLL动态链接库的文件吗?
    如果是对方写的函数说明,绿色部分段落就是申明出现问题的函数
    SEN_ReadDSPData
    int SEN_ReadDSPData(stCHANNEL_LIST pChannelData[11])
    参数:
    [out] stCHANNEL_LIST pChannelData[11]:返回最多11通道100赫兹的波长数据。(0~10依次为1~11通道序列),数据结构说明详见下面。
    结构体说明:
    struct stCHANNEL_SENSOR_LIST {
    int nSensorCount; 该通道的传感器数。
    std::vector<float> fWaveLengthVec; 该通道的传感器波长序列。
    std::vector<float> fPowerDBVec; 该通道的传感器功率序列。}; 
    struct stCHANNEL_LIST {
    int nChNum; 通道号。
    int nFreq; 该时间内采集的频率。
    std::vector<stCHANNEL_SENSOR_LIST> tSensorListVec; 传感器序列。};返回值:
    0,表示读取成功;非0,读取失败。
      

  16.   


    如果在 VC++ 中没有声明为 int __stdcall SEN_ReadDSPData(stCHANNEL_LIST *pChannelData),在 VB 中就不可直接调用。VB 是默认标准调用的。解决方法:1 改 DLL。这个最简单。2 再写一个 DLL,作为标准调用接口。甚至可以把原 DLL 打包。3 最麻烦的,在 VB 中声明类来调用。我在原来回帖中曾有源码示例,搜搜。
      

  17.   


    谢谢,现在确认是对方的VC DLL不能直接被VB调用请问下前辈原来的回帖怎么搜索呢?我不太会使用论坛的功能。
      

  18.   

    请问int SEN_ReadDSPData(stCHANNEL_LIST pChannelData[11])修改为int __stdcall SEN_ReadDSPData(stCHANNEL_LIST *pChannelData),请问原VC语句里的[11]不需要了吗?
    std::vector<float> fWaveLengthVec; 该通道的传感器波长序列。
    std::vector<float> fPowerDBVec; 该通道的传感器功率序列。
    std::vector<stCHANNEL_SENSOR_LIST> tSensorListVec; 传感器序列。
    有其他前辈说里面结构体参数std::vector 应该是 VC 特有类,不能在 VC 之外调用。请问这样确定目前VB没法调用这3个结构体参数吗,如果让对方程序员帮忙修改,这3个结构体参数也需要改吗?请各位前辈不吝赐教,谢谢。
      

  19.   

    有前辈能帮忙下吗,这两天在网上搜索了大量的资料,自己都弄糊涂了,跟对方程序员联系表示不可能为你一个人改VC DLL 请问这些VB中执行错误究竟是哪出错了呀?
      

  20.   


    目前比较简单的处理方式,是自己用 VC++ 写一个接口 DLL,其中调用原 DLL 。里面所有的函数都比照原来的写法,仅仅加上 __stdcall 关键字。为了区别,函数名可以前缀一些你自己的东西。函数内容就是调用原来的函数。生成 DLL 之后,你调自己的 DLL 就可以了。
      

  21.   


    谢谢前辈,这个方法确实比较简便,但是我从来没使用过C++,安装C++打开对整个界面毫无头绪,也不知道怎么写新DLL来调用原有DLL......昨天和对方程序员商量,他发了C++的调用源代码给我参考,但是关于SEN_ReadDSPData这个函数如何调用看得不是很明白,语句方面也不能理解并转换成VB语句  public partial class Form1 : Form
        {
            #region struc declare
            /// <summary>
            /// 原型定义
            /// </summary>
            const int MaxSensorCountPerChannel = 30;
            const int MaxFreq = 150;
            const int MaxChannelNum = 33;
            [StructLayout(LayoutKind.Sequential)]
            private struct SensorList
            {
                public int nSensorCount;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxSensorCountPerChannel)]
                public float[] fWaveLengthVec;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxSensorCountPerChannel)]
                public float[] fPowerDBVec;
            }
            [StructLayout(LayoutKind.Sequential)]
            private struct PerChannel
            {
                public int nChNum;
                public int nFreq;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxFreq)]
                public SensorList[] tSensorListVec;
            }
            #endregion        #region import dll
            /// <summary>
            /// 函数封装
            /// </summary>
            /// <returns></returns>
            [DllImport("ReadData.dll")]
            private static extern int SEN_Init();        [DllImport("ReadData.dll")]
            private static extern void SEN_Close();        [DllImport("ReadData.dll")]
            private static extern void SEN_ReadDSPData(IntPtr pp);
            [DllImport("ReadData.dll")]
            private static extern bool SEN_IsConnected();        [DllImport("ReadData.dll")]
            private static extern int SEN_SendParaData();
            #endregion        #region dll function
            private static int DllInit()
            {
                int rtn = -1;
                try
                {
                    rtn = SEN_Init();
                }
                catch
                {
                    rtn = -2;
                }
                return rtn;
            }        private static int IsConnected()
            {
                int ret = 0;
                if (!SEN_IsConnected())
                {
                    ret = -1;
                }
                return ret;
            }        private static int SendParaData()
            {
                int ret = 0;
                if (SEN_SendParaData() != 0)
                {
                    ret = -2;
                }
                return ret;
            }        private static void DspClose()
            {
                SEN_Close();
            }
            /// <summary>
            /// 获取数据
            /// </summary>
            /// <returns></returns>
            private static PerChannel[] GetDataUseDll()
            {
               PerChannel[] channelList = new PerChannel[MaxChannelNum];
               try
               {
                   for (int i = 0; i < channelList.Length; i++)
                   {
                       channelList[i] = new PerChannel();
                   }
                   IntPtr[] ptArray = new IntPtr[1];
                   IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (PerChannel))*MaxChannelNum);
                   Marshal.Copy(ptArray, 0, pt, 1);               SEN_ReadDSPData( pt);
                   for (int i = 0; i < channelList.Length; i++)
                   {
                       channelList[i] =
                           (PerChannel)
                           Marshal.PtrToStructure((IntPtr) ((UInt32) pt + i*Marshal.SizeOf(typeof (PerChannel))),
                                                  typeof (PerChannel));
                   }               Marshal.FreeHGlobal(pt);
                 }
               catch (Exception ex)
               {
                   MessageBox.Show(ex.Message);
               }           return channelList;        }
            #endregion
      

  22.   

    2
    http://support.microsoft.com/kb/153586/en-us3
    http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention.aspx