public
Created

How to export symbols from .exe files and link against it

  • Download Gist
Rakefile
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
require 'rake/clean'
 
CLEAN.include '*.{a,o,def,exe,dll}'
 
file 'vm.exe' => ['main.c', 'interface.h'] do |t|
cfiles = t.prerequisites.reject { |f| f !~ /\.c$/ }
 
cfiles.each do |f|
sh "gcc -c #{f} -o #{f.ext('.o')} -DRBX_WINDOWS -DRBX_BUILDING_VM"
end
 
ofiles = cfiles.map { |f| f.ext('.o') }
 
sh "gcc -o #{t.name} #{ofiles.join(' ')}"
end
 
file 'libvm.a' => ['vm.exe'] do |t|
exe = t.prerequisites.first
cfiles = Rake::Task[exe].prerequisites.reject { |f| f !~ /\.c$/ }
ofiles = cfiles.map { |f| f.ext('.o') }
 
sh "dlltool --dllname #{exe} --output-lib #{t.name} #{ofiles.join(' ')}"
end
 
file 'extension.def' do |t|
File.open(t.name, 'w') do |f|
f.puts 'EXPORTS'
f.puts "Init_#{t.name.ext('')}"
end
end
 
file 'extension.so' => ['extension.c', 'interface.h', 'extension.def', 'libvm.a'] do |t|
cfiles = t.prerequisites.reject { |f| f !~ /\.c$/ }
libs = t.prerequisites.reject { |f| f !~ /\.a$/ }
libs.map! { |l| l.gsub('lib', '-l').ext('') }
 
sh "gcc -shared -o #{t.name} #{cfiles.join(' ')} -L. -Wl,--enable-auto-image-base,--enable-auto-import #{t.name.ext('.def')} #{libs.join(' ')}"
end
 
task :run => ['vm.exe', 'extension.so'] do
sh "vm loadext"
end
extension.c
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <stdio.h>
#include "interface.h"
 
void define_stuff()
{
printf("here we define some stuff\n");
}
 
void Init_extension()
{
printf("Hello from extension\n");
rb_hello();
define_stuff();
}
interface.h
C
1 2 3 4 5 6 7 8 9 10 11
#ifdef RBX_WINDOWS
#ifdef RBX_BUILDING_VM
#define RUBY_EXTERN extern __declspec(dllexport)
#else
#define RUBY_EXTERN extern __declspec(dllimport)
#endif
#else
#define RUBY_EXTERN extern
#endif
 
RUBY_EXTERN void rb_hello();
main.c
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#include <stdio.h>
#include "interface.h"
 
#ifdef RBX_WINDOWS
#include <windows.h>
#endif
 
RUBY_EXTERN void rb_hello()
{
printf("Hello from rb_hello()\n");
}
 
int main(int argc, char* argv[])
{
int i;
 
printf("Hello from main()\n");
 
if (argv[1])
{
#ifdef RBX_WINDOWS
HMODULE handle;
FARPROC symbol;
char *ext = "extension.so";
char *init = "Init_extension";
 
printf("Loading %s\n", ext);
 
// Ruby 1.9 behavior (first look into system, then local path)
handle = LoadLibraryEx((LPSTR)ext, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
 
if (!handle)
{
printf("Error loading %s\n", ext);
return -1;
}
 
printf("Getting address of %s\n", init);
symbol = GetProcAddress(handle, init);
 
printf("Invoking %s\n", init);
symbol();
 
printf("Releasing %s\n", ext);
FreeLibrary(handle);
#endif
}
 
return 0;
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.