Не может переменная доступа в C++ DLL из приложения C

Самый простой способ:

void sendFCMPush(String msg,String token) {
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    httpClient.addInterceptor(new Interceptor() {
        @Override
        public okhttp3.Response intercept(Chain chain) throws IOException {
            Request original = chain.request();

            // Request customization: add request headers
            Request.Builder requestBuilder = original.newBuilder()
                    .header("Authorization", "key="+Const.FIREBASE_LEGACY_SERVER_KEY); // <-- this is the important line
            Request request = requestBuilder.build();
            return chain.proceed(request);
        }
    });

    httpClient.addInterceptor(logging);
    OkHttpClient client = httpClient.build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://fcm.googleapis.com/")//url of FCM message server
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())//use for convert JSON file into object
            .build();

    // prepare call in Retrofit 2.0
    FirebaseAPI firebaseAPI = retrofit.create(FirebaseAPI.class);

    //for messaging server
    NotifyData notifydata = new NotifyData("Chatting", msg);

    Call<Message> call2 = firebaseAPI.sendMessage(new Message(token, notifydata));

    call2.enqueue(new Callback<Message>() {
        @Override
        public void onResponse(Call<Message> call, retrofit2.Response<Message> response) {
            Log.e("#@ SUCCES #E$#", response.body().toString());
        }

        @Override
        public void onFailure(Call<Message> call, Throwable t) {

            Log.e("E$ FAILURE E$#", t.getMessage());
        }
    });
}

Создать класс для создания объекта:

public class Message {
String to;
NotifyData data;

public Message(String to, NotifyData data) {
    this.to = to;
    this.data = data;
}
}

Создать класс для создания объекта:

public class Notification {
String title;
String message;
enter code here`enter code here`
public Notification(String title, String message) {
    this.title = title;
    this.message = message;
}
}
7
задан agf 29 September 2011 в 14:59
поделиться

7 ответов

необходимо связаться против lib, сгенерированного после компиляции DLL. В опциях компоновщика проекта необходимо добавить .lib файл. И да, необходимо также объявить переменную как:

extern "C" { declspec(dllimport) char MyNewVariable; }
5
ответ дан 6 December 2019 в 15:40
поделиться

экстерн "C" - то, как Вы удаляете художественное оформление - оно должно работать для использования:

экстерн "C" declspec (dllimport) символьный MyNewVariable;

или если Вы хотите заголовок, который может использоваться C++ или C (с / переключателем TC)

#ifdef __cplusplus
extern "C" {
#endif
declspec(dllimport) char MyNewVariable;
#ifdef __cplusplus
}
#endif

И конечно, ссылка с библиотекой импорта, сгенерированной dll выполнение экспорта.

4
ответ дан 6 December 2019 в 15:40
поделиться

Я не уверен, кто downmodded botismarius, потому что он прав. Причиной является сгенерированный .lib, библиотека импорта, которая помогает просто объявить внешнюю переменную / функция с __declspec(dllimport) и просто используйте его. Библиотека импорта просто автоматизирует необходимое LoadLibrary() и GetProcAddress() вызовы. Без него необходимо назвать их вручную.

2
ответ дан 6 December 2019 в 15:40
поделиться

Они оба правы. То, что сообщение об ошибке описывает __imp_?MyNewVariable@@3PADA средства, что это ищет украшенное имя, таким образом, экстерн "C" необходим. Однако соединение с библиотекой импорта также необходимо, или Вы просто получите другую ошибку ссылки.

1
ответ дан 6 December 2019 в 15:40
поделиться

@Graeme: Вы правы на этом, также. Я думаю "C" компилятор, который использует OP, не осуществляет стандарт C99, но компилирует как C++, таким образом искажая имена. Истинный компилятор C не понял бы "C" часть extern "C" ключевое слово.

1
ответ дан 6 December 2019 в 15:40
поделиться

В dll исходном коде у Вас должна быть эта реализация так, чтобы .lib файл экспортировал символ:

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

C клиент должен использовать заголовок с этим объявлением так, чтобы клиентский код импортировал символ:

extern "C" _declspec(dllimport) char* MyNewVariable;

Этот заголовок вызовет ошибку компиляции, если #include-ed в dll исходном коде, таким образом, это обычно помещается в заголовок экспорта, который используется только для экспортируемых функций и только клиентами.

Если Вы должны, можно также создать "универсальный" заголовок, который может быть включен где угодно, который похож на это:

#ifdef __cplusplus
extern "C" {
#endif
#ifdef dll_source_file
#define EXPORTED declspec(dllexport) 
#else
#define EXPORTED declspec(dllimport) 
#endif dll_source_file
#ifdef __cplusplus
}
#endif

EXPORTED char* MyNewVariable;

Затем dll исходный код похож на это:

#define dll_source_code 
#include "universal_header.h"

EXPORTED char* MyNewVariable = 0;

И клиент похож на это:

#include "universal_header.h"
...
MyNewVariable = "Hello, world";

Если Вы делаете это много, монстр #ifdef наверху может войти в export_magic.h, и universal_header.h становится:

#include "export_magic.h"

EXPORTED char *MyNewVariable;
1
ответ дан 6 December 2019 в 15:40
поделиться

Я никогда не использовал _declspec (dllimport), когда я программировал в Windows. Необходимо смочь просто объявить

extern "C" char* MyNewVariable;

и свяжитесь с .libb, созданным, когда DLL был скомпилирован.

0
ответ дан 6 December 2019 в 15:40
поделиться