Как я могу вызывать функции C из Swift, используя оболочку, и компилировать с помощью терминала?

#c #swift

#c #swift

Вопрос:

Это мой код на c :

 #include<stdio.h>
#include<string.h>
#include "agg-2.5/include/agg_rendering_buffer.h"
#include "r_buffer.h"
enum{
  frame_width = 320,
  frame_height = 200
};

bool write_ppm(const unsigned char* buf,
                unsigned width,
                unsigned height,
                const char* file_name)
                {
                  FILE* fd = fopen(file_name, "wb");
                  if(fd){
                    fprintf(fd, "P6 %d %d 255 ", width, height);
                    fwrite(buf, 1, width*height*3, fd);
                    fclose(fd);
                    return true;
                  }
                  return false;
                }

void draw_black_frame(agg::rendering_bufferamp; rbuf){
  unsigned i;
  for(i = 0; i<rbuf.height();i  ){
    unsigned char* p = rbuf.row_ptr(i);
    *p   = 0; *p   = 0; *p   = 0;
    p  = (rbuf.width() - 2)*3;
    *p   = 0; *p   = 0; *p   = 0;
  }
  memset(rbuf.row_ptr(0), 0, rbuf.width()*3);
  memset(rbuf.row_ptr(rbuf.height()-1), 0, rbuf.width()*3);
}

void start_func() {

  unsigned char* buffer = new unsigned char[frame_width*frame_height*3];

  memset(buffer, 255, frame_width*frame_height*3);

  agg::rendering_buffer rbuf(buffer,
                            frame_width,
                            frame_height,
                            frame_width*3);

  unsigned i;
  for(i = 0; i<rbuf.height()/2;  i){
    unsigned char* ptr = rbuf.row_ptr(i)   i*3;

    *ptr   = 127;// R
    *ptr   = 200;// B
    *ptr   = 98; // G
  }

  draw_black_frame(rbuf);
  write_ppm(buffer, frame_width, frame_height, "agg_test.ppm");

  delete [] buffer;

}
  

r_buffer.h

 extern "C" {
  void start_func();
}
  

bridge.h

 #include "r_buffer.h"
  

swift_r_buffer.swift

 start_func();
  

Я пытаюсь скомпилировать его следующим образом:

 swiftc swift_r_buffer.swift -import-objc-header bridge.h
  

Но я получаю эту ошибку:

 /home/karthik/agg_eg/bridge.h:1:10: note: in file included from /home/karthik/agg_eg/bridge.h:1:
#include "r_buffer.h"
         ^
/home/karthik/agg_eg/./r_buffer.h:1:8: error: expected identifier or '('
extern "C" {
       ^
1 error generated.
<unknown>:0: error: failed to emit precompiled header '/tmp/bridge-238ccd.pch' for bridging header 'bridge.h'
<unknown>:0: error: generate-pch command failed with exit code 1 (use -v to see invocation)
  

Как я могу это решить? Я использую Ubuntu 18.04 LTS.

Ответ №1:

Мост должен быть на C, поэтому вам нужно, чтобы extern "C" директива была обусловлена тем, что целью является C .
Что-то вроде этого:

 #ifdef __cplusplus
extern "C" {
#endif

  void start_func(void);

#ifdef __cplusplus
}
#endif
  

Комментарии:

1. В этом случае я получаю: /tmp/swift_r_buffer-01a192.o:swift_r_buffer-01a192.o: функция main: ошибка: неопределенная ссылка на ‘start_func’ clang: ошибка: команда компоновщика не удалась с кодом выхода 1 (используйте -v, чтобы увидеть вызов) <неизвестно>:0: ошибка: команда link не удалась с кодом выхода 1 (используйте -v, чтобы увидеть вызов) <неизвестно>:0: ошибка: команда link не удалась с кодом выхода 1 (используйте -v, чтобы увидеть вызов)

Ответ №2:

Я решил проблему. Вам нужно скомпилировать файл c

 g   r_buffer.c   -c
  

Затем создайте библиотеку

 ar r libr_buffer.a r_buffer.o
  

Затем скомпилируйте файл swift следующим образом

 swiftc swift_r_buffer.swift libr_buffer.a -import-objc-header bridge.h 
  

Затем вы можете запустить его следующим образом

 ./main