简体   繁体   English

使用链接器选择C ++函数的实现

[英]Selecting implementations of C++ functions using the linker

I would like to test C++ functions in a piece of code by swapping them one by one for ones that are known to work in a working context, where the swapping is done using the linker. 我想在一段代码中测试C ++函数,将它们逐个交换为已知在工作上下文中工作的函数,其中交换是使用链接器完成的。 (I use C++ with GCC under linux.) Unfortunately I do not know enough about how to drive the linker to know how to do this or even if it is possible. (我在Linux下使用C ++与GCC。)不幸的是,我不知道如何驱动链接器知道如何做到这一点,或者即使它是可能的。

For me, the main reason is to test students' code against a teacher's model solution, though I can imagine plenty of other cases where such methods may be of interest. 对我来说,主要原因是针对教师的模型解决方案测试学生的代码,尽管我可以想象很多其他可能感兴趣的方法。 Note that the students' source code is available and can be compiled in any way I like, but this source cannot be edited. 请注意,学生的源代码是可用的,可以以我喜欢的任何方式编译,但无法编辑此源。 However, the teacher's code can be modified as needed. 但是,可以根据需要修改教师的代码。

There follows a simple example that shows the idea. 下面是一个简单的例子,展示了这个想法。

Here is, the teacher's code, in which the functions can call each other in ways similar to that shown. 这是教师的代码,其中的功能可以用类似于所示的方式相互调用。 All functions here are assumed to meet their specifications exactly. 假设这里的所有功能都完全符合他们的规格。

#include <iostream>

using namespace std;

// model teacher program : main calls g which calls f

int f(int x) {
  cout << "in teacher-f(" << x << ")" << endl;
  return 46;
}

int g(int x) {
  cout << "in teacher-g(" << x << ")" << endl;
  int y = f(x);
  cout << "f(" << x << ") returned " << y << endl;  
  return 91;  
}

int main() {
  cout << "in teacher-main()" << endl;
  int x = 2;
  int y = g(x);
  cout << "g(" << x << ") returned " << y <<  endl;  
}

A typical student's code, attempting to meet the same specifications, to be tested. 一个典型的学生代码,试图满足相同的规范,进行测试。 In my case a "main", several #includes, and "using namespace std;" 在我的例子中是一个“main”,几个#includes和“using namespace std;” would be expected. 会有所期待。

#include <iostream>

using namespace std;

// model student program : main calls g which calls f

int f(int x) {
  cout << "in student-f(" << x << ")" << endl;
  return 27;
}

int g(int x) {
  cout << "in student-g(" << x << ")" << endl;
  int y = f(x);
  cout << "f(" << x << ") returned " << y << endl;  
  return 82;  
}

int main() {
  cout << "in student-main()" << endl;
  int x = 4;
  int y = g(x);
  cout << "g(" << x << ") returned " << y <<  endl;  
  return 0;
}

I want to swap each of the teacher's functions one by one to test each student function individually. 我想逐个交换每个教师的功能,分别测试每个学生的功能。

Here is one attempt, in this case testing the student's g() 这是一次尝试,在这种情况下测试学生的g()

g++ -c student.cpp
# (this makes student.o)
# strip f() and main() from student.o:
strip -N main -N _Z1fi student.o

# similarly for teacher, but stripping g
g++ -c teacher.cpp
strip -N _Z1gi teacher.o
g++ -o final teacher.o student.o
./final

and the result I would expect is 我期望的结果是

in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(4) returned 82

unfortunately, I get: 不幸的是,我得到:

strip: not stripping symbol `_Z1fi' because it is named in a relocation

I have tried doing something similar with .so libraries instead. 我尝试过用.so库做类似的事情。 The error message to strip disappears, but unfortunately this time the teacher main calls the teacher g that I had tried to remove. 剥离的错误消息消失了,但不幸的是,这次老师主要打电话给我试图删除的老师。

g++ -shared -fPIC -o student.so student.cpp
g++ -shared -fPIC -o teacher.so teacher.cpp 
strip -N main -N _Z1fi student.so
strip -N _Z1gi  teacher.so
g++ -o final teacher.so student.so
./final

giving

in teacher-main()
in teacher-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 91

Any suggestions? 有什么建议么? Is this even possible? 这甚至可能吗? If not, is there any way round to do the same thing? 如果没有,有没有办法做同样的事情? As said I cannot edit student.cpp, but I could #include it from other source code. 如上所述,我无法编辑student.cpp,但我可以从其他源代码#include它。

Thanks Richard 谢谢理查德

This somewhat violates your requirements, but I would suggest you to change the expected form of student's code. 这有点违反了您的要求,但我建议您更改学生代码的预期形式。 Do not require them to code main , or ask then to code main in a separate compilation unit, or just ask them to rename their main to say main_ before submission. 不要求他们编写main代码,或者要求在单独的编译单元中编写main代码,或者只是要求他们在提交之前将其main重命名为main_ Or just add #define main main_ to the top of student's code after the submission before the compilation; 或者在编译之前提交之后,将#define main main_添加到学生代码的顶部; for simple tasks this will be enough. 对于简单的任务,这就足够了。

After that, you do not need to strip anything from compiled code. 之后,您不需要从编译代码中删除任何内容。 Just place all your functions to namespace teacher , write your own main that will do all needed work, and link all code together. 只要将您的所有功能, namespace teacher ,写自己的main ,将尽一切必要的工作,并链接在一起的所有代码。 Change and recompile your code to call teacher::f for your function, or ::f for the student's function. 更改和重新编译代码来调用teacher::f为你的函数,或::f对学生的功能。

I think the only possible solution is to separate it to two files: 我认为唯一可行的解​​决方案是将其分为两个文件:

1st file should be common for teacher and student and may contain both main and f + forward declaration for g : 第一个文件对于老师和学生应该是通用的,并且可以包含g mainf + forward声明:

common file: (common.cpp) 常用文件:(common.cpp)

#include <iostream>    
using namespace std;
int g(int x) ;

int f(int x) {
  cout << "in teacher-f(" << x << ")" << endl;
  return 46;
}

int main() {
  cout << "in teacher-main()" << endl;
  int x = 2;
  int y = g(x);
  cout << "g(" << x << ") returned " << y <<  endl;  
}

2nd file should contain the g method (+ forward declaration to f ): 第二个文件应该包含g方法(+ f前向声明):

teacher(teacher.cpp): 老师(teacher.cpp):

#include <iostream>
using namespace std;
int f(int x);

int g(int x) {
  cout << "in teacher-g(" << x << ")" << endl;
  int y = f(x);
  cout << "f(" << x << ") returned " << y << endl;  
  return 91;  
}

student (student.cpp): 学生(student.cpp):

#include <iostream>
using namespace std;
int f(int x);

int g(int x) {
  cout << "in student-g(" << x << ")" << endl;
  int y = f(x);
  cout << "f(" << x << ") returned " << y << endl;  
  return 82;  
}

now you can compile teacher from common.cpp + teacher.cpp 现在你可以从common.cpp + teacher.cpp编译老师了

g++ -o teacher common.cpp teacher.cpp

and student from common.cpp + student.cpp 和来自common.cpp + student.cpp的学生

g++ -o student common.cpp student.cpp

The common.cpp can be even replaced by a static or shared library and you can add a header instead of the forward declaration of f . common.cpp甚至可以被静态库或共享库替换,你可以添加一个头而不是f的前向声明。

This was from Lawrence and answers my question. 这是来自劳伦斯并回答了我的问题。 I can't say about portability etc. 关于便携性等我不能说

g++ -c student.cpp
g++ -c teacher.cpp 
strip -N main student.o
objcopy -W _Z1fi student.o
objcopy -W _Z1gi  teacher.o
g++ -o final teacher.o student.o
./final

giving the expected 给出预期的

in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 82

Thanks! 谢谢!

PS I must have made a typo first time I tried it, or else the order of stripping and weakening is important... my comment to say this objcopy -W idea doesn't work has now been deleted. PS我第一次尝试时必须写错字,否则剥离和弱化的顺序很重要......我的评论说这个objcopy -W想法不起作用现在已被删除。 The above has been tested a few times now. 以上已经过几次测试了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM