首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >__stdcall ESP腐败

__stdcall ESP腐败
EN

Stack Overflow用户
提问于 2014-01-10 08:31:06
回答 1查看 509关注 0票数 0

在尝试通过JNA回调从C++应用程序获得通知时,我经常看到JVM崩溃。Native.setProtected帮不上忙。原始回调声明是

代码语言:javascript
复制
typedef void (__stdcall *TRANS2QUIK_ORDER_STATUS_CALLBACK) (long nMode, DWORD dwTransID, double dNumber, LPCSTR ClassCode, LPCSTR SecCode, double dPrice, long nBalance, double dValue, long nIsSell, long nStatus, long nOrderDescriptor);

^这是不工作的

我尝试了两个应该工作的StdCallLibrary.StdCallCallback和简单的回调,它们都失败了。但是,在我编写了C++包装器之后,我只将JNA回调作为cdecl从原始的C++ stdcall内部调用,一切都开始顺利进行。

代码语言:javascript
复制
typedef void (*WRAPPED_ORDER_STATUS_CALLBACK) (double dNumber, double dPrice, long nBalance, double dValue, long nIsSell, long nStatus, long nOrderDescriptor);  

QUIKWRAP_API TRANS2QUIK_ORDER_STATUS_CALLBACK __stdcall wrapCallback(WRAPPED_ORDER_STATUS_CALLBACK);

^这是工作平稳的w/o问题

问题是,这是否是专门针对此函数签名的JNA缺陷?因为我的代码中有另一个带有不同签名的stdcall,所以它运行得很好。

我为这个问题创建了一个独立的测试用例,请参阅下面的

代码语言:javascript
复制
import java.util.HashMap;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.win32.StdCallLibrary;


public class JNATest {
    interface TestCallback extends StdCallLibrary.StdCallCallback {
        void testCallback(NativeLong nMode, WinDef.DWORD dwTransID, double dNumber, LPCSTR ClassCode, LPCSTR SecCode, double dPrice, NativeLong nBalance, double dValue, NativeLong nIsSell, NativeLong nStatus, NativeLong nOrderDescriptor);
    }

    interface JNADLL extends StdCallLibrary{
        void testCallback(TestCallback cb);
    }
    public static class LPCSTR extends PointerType {
        public LPCSTR(Pointer address) {
            super(address);
        }
        public LPCSTR() {
            super();
        }
        @Override
        public String toString() {
            return getPointer().getString(0);
        }
    };



    /**
     * @param args
     */
    public static void main(String[] args) {
        System.setProperty("jna.encoding", "Cp1251");

        HashMap<String, Object> nameMapping = new HashMap<String, Object>();

        nameMapping.put(Library.OPTION_FUNCTION_MAPPER, StdCallLibrary.FUNCTION_MAPPER);
        nameMapping.put(Library.OPTION_CALLING_CONVENTION, StdCallLibrary.STDCALL_CONVENTION);

        JNADLL JNADll = (JNADLL) Native.loadLibrary("QuikWrap", JNADLL.class, nameMapping);

        TestCallback cb = new TestCallback() {

            @Override
            public void testCallback(NativeLong nMode, DWORD dwTransID,
                    double dNumber, JNATest.LPCSTR ClassCode, JNATest.LPCSTR SecCode,
                    double dPrice, NativeLong nBalance, double dValue,
                    NativeLong nIsSell, NativeLong nStatus, NativeLong nOrderDescriptor) {
                System.out.println("testCallback  \n" +
                        "  nMode: " + nMode + "\n" +
                        "  dwTransID: " + dwTransID + "\n" +
                        "  number: " + dNumber + "\n" +
                        "  ClassCode: " + ClassCode + "\n" +
                        "  SecCode: " + SecCode + "\n" +
                        "  price: " + dPrice + "\n" +
                        "  balance: " + nBalance + "\n" +
                        "  value: " + dValue + "\n" +
                        "  isSell: " + nIsSell + "\n" +
                        "  status: " + nStatus + "\n" +
                        "  orderDescriptor: " + nOrderDescriptor + "\n");
            }
        };
        JNADll.testCallback(cb);
    }

}

C标题QuikWrap.h

代码语言:javascript
复制
#ifdef QUIKWRAP_EXPORTS
#define QUIKWRAP_API extern "C"__declspec(dllexport) 
#else
#define QUIKWRAP_API __declspec(dllimport)
#endif
typedef void (__stdcall *TRANS2QUIK_ORDER_STATUS_CALLBACK) (long nMode, DWORD dwTransID, double dNumber, LPCSTR ClassCode, LPCSTR SecCode, double dPrice, long nBalance, double dValue, long nIsSell, long nStatus, long nOrderDescriptor);
QUIKWRAP_API void __stdcall testCallback(TRANS2QUIK_ORDER_STATUS_CALLBACK cb);

C源QuikWrap.cpp

代码语言:javascript
复制
#include "stdafx.h"
#include "QuikWrap.h"
#include "stdio.h"

QUIKWRAP_API void __stdcall testCallback(TRANS2QUIK_ORDER_STATUS_CALLBACK cb){
    cb(1, 2, 3, "Hi", "Bye", 4.0, 5, 6, 7, 8, 9);
    cb(0, 2, 3, "Hi", "Bye", 4.0, 5, 6, 7, 8, 9);
    return;
}

我得到的唯一的回调输出是

代码语言:javascript
复制
testCallback  
  nMode: 1
  dwTransID: 2
  number: 3.0
  ClassCode: Hi
  SecCode: Bye
  price: 4.0
  balance: 5
  value: 6.0
  isSell: 7
  status: 8
  orderDescriptor: 9

然后在退出时失败。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-13 12:42:14

该问题是由于libffi中的一个错误造成的,在该错误中,堆栈对齐是根据参数大小进行调整的,这对于stdcall来说是不正确的行为。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21039368

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档